初始化项目 #1

Closed
pub49nk5s wants to merge 0 commits from master into develop

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
</profile>
</annotationProcessing>
<bytecodeTargetLevel>
<module name="OpenRokcet" target="1.7" />
<module name="SSM_Stuct" target="1.7" />
<module name="swing" target="11" />
</bytecodeTargetLevel>
</component>
</project>

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
</component>
</project>

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/swing/pom.xml" />
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
<option name="ignoredFiles">
<set>
<option value="$PROJECT_DIR$/pom.xml" />
<option value="$PROJECT_DIR$/swing/pom.xml" />
</set>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="11" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/OpenRocket Core.iml" filepath="$PROJECT_DIR$/OpenRocket Core.iml" />
<module fileurl="file://$PROJECT_DIR$/OpenRocket Swing.iml" filepath="$PROJECT_DIR$/OpenRocket Swing.iml" />
<module fileurl="file://$PROJECT_DIR$/OpenRocket Test Libraries.iml" filepath="$PROJECT_DIR$/OpenRocket Test Libraries.iml" />
</modules>
</component>
</project>

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="eclipse" classpath-dir="$MODULE_DIR$/core" type="JAVA_MODULE" version="4" />

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="eclipse" classpath-dir="$MODULE_DIR$/swing" type="JAVA_MODULE" version="4" />

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="eclipse" classpath-dir="$MODULE_DIR$/lib-test" type="JAVA_MODULE" version="4" />

@ -1,13 +1,13 @@
; Raketenmodellbau Klima GmbH
; Official manufacturer thrust data - A6
; Created by Leo Nutz for OpenRocket,
; released into the Public Domain (3/2014)
A6 18 70 4 0.0035 0.0145 Klima
0.088 0.502
0.186 4.601
0.232 7.089
0.314 10.477
0.418 6.713
0.467 3.011
0.501 0.418
0.71 0.0
; Raketenmodellbau Klima GmbH
; Official manufacturer thrust data - A6
; Created by Leo Nutz for OpenRocket,
; released into the Public Domain (3/2014)
A6 18 70 4 0.0035 0.0145 Klima
0.088 0.502
0.186 4.601
0.232 7.089
0.314 10.477
0.418 6.713
0.467 3.011
0.501 0.418
0.71 0.0

@ -1,27 +1,27 @@
; Raketenmodellbau Klima GmbH
; Official manufacturer thrust data - B4
; Created by Leo Nutz for OpenRocket,
; released into the Public Domain (3/2014)
B4 18 70 0-4 0.0054 0.0163 Klima
0.049 0.83
0.096 1.745
0.157 2.946
0.209 3.89
0.273 4.977
0.335 6.093
0.380 7.122
0.411 8.001
0.436 7.065
0.465 6.236
0.516 5.063
0.564 4.462
0.607 4.205
0.669 4.09
0.90 4.09
0.966 3.976
1.025 3.719
1.084 3.261
1.145 2.546
1.212 1.745
1.295 0.772
1.364 0.0
; Raketenmodellbau Klima GmbH
; Official manufacturer thrust data - B4
; Created by Leo Nutz for OpenRocket,
; released into the Public Domain (3/2014)
B4 18 70 0-4 0.0054 0.0163 Klima
0.049 0.83
0.096 1.745
0.157 2.946
0.209 3.89
0.273 4.977
0.335 6.093
0.380 7.122
0.411 8.001
0.436 7.065
0.465 6.236
0.516 5.063
0.564 4.462
0.607 4.205
0.669 4.09
0.90 4.09
0.966 3.976
1.025 3.719
1.084 3.261
1.145 2.546
1.212 1.745
1.295 0.772
1.364 0.0

@ -1,24 +1,24 @@
; Raketenmodellbau Klima GmbH
; Official manufacturer thrust data - C2
; Created by Leo Nutz for OpenRocket,
; released into the Public Domain (3/2014)
C2 18 70 0-P 0.0113 0.0224 Klima
0.04 0.229
0.12 0.658
0.211 1.144
0.291 1.831
0.385 2.86
0.447 3.833
0.505 5.001
0.567 3.89
0.615 3.146
0.665 2.66
0.735 2.203
0.815 2.088
0.93 1.98
4.589 1.96
4.729 1.888
4.815 1.602
4.873 1.259
4.969 0.658
5.083 0.0
; Raketenmodellbau Klima GmbH
; Official manufacturer thrust data - C2
; Created by Leo Nutz for OpenRocket,
; released into the Public Domain (3/2014)
C2 18 70 0-P 0.0113 0.0224 Klima
0.04 0.229
0.12 0.658
0.211 1.144
0.291 1.831
0.385 2.86
0.447 3.833
0.505 5.001
0.567 3.89
0.615 3.146
0.665 2.66
0.735 2.203
0.815 2.088
0.93 1.98
4.589 1.96
4.729 1.888
4.815 1.602
4.873 1.259
4.969 0.658
5.083 0.0

@ -1,21 +1,21 @@
; Raketenmodellbau Klima GmbH
; Official manufacturer thrust data - C6
; Created by Leo Nutz for OpenRocket,
; released into the Public Domain (3/2014)
C6 18 70 0-3-5-7-P 0.0096 0.0205 Klima
0.046 0.953
0.168 5.259
0.235 10.023
0.291 15.00
0.418 9.87
0.505 7.546
0.582 6.631
0.679 6.136
0.786 5.716
1.26 5.678
1.357 5.488
1.423 4.992
1.469 4.116
1.618 1.22
1.701 0.0
; Raketenmodellbau Klima GmbH
; Official manufacturer thrust data - C6
; Created by Leo Nutz for OpenRocket,
; released into the Public Domain (3/2014)
C6 18 70 0-3-5-7-P 0.0096 0.0205 Klima
0.046 0.953
0.168 5.259
0.235 10.023
0.291 15.00
0.418 9.87
0.505 7.546
0.582 6.631
0.679 6.136
0.786 5.716
1.26 5.678
1.357 5.488
1.423 4.992
1.469 4.116
1.618 1.22
1.701 0.0

@ -1,28 +1,28 @@
; Raketenmodellbau Klima GmbH
; Official manufacturer thrust data - D3
; Created by Leo Nutz for OpenRocket,
; released into the Public Domain (3/2014)
D3 18 70 0-P 0.017 0.0279 Klima
0.073 0.229
0.178 0.686
0.251 1.287
0.313 2.203
0.375 3.633
0.425 5.006
0.473 6.465
0.556 8.181
0.603 9.01
0.655 6.922
0.698 5.463
0.782 4.291
0.873 3.576
1.024 3.146
1.176 2.946
5.282 2.918
5.491 2.832
5.59 2.517
5.782 1.859
5.924 1.287
6.061 0.715
6.17 0.286
6.26 0.0
; Raketenmodellbau Klima GmbH
; Official manufacturer thrust data - D3
; Created by Leo Nutz for OpenRocket,
; released into the Public Domain (3/2014)
D3 18 70 0-P 0.017 0.0279 Klima
0.073 0.229
0.178 0.686
0.251 1.287
0.313 2.203
0.375 3.633
0.425 5.006
0.473 6.465
0.556 8.181
0.603 9.01
0.655 6.922
0.698 5.463
0.782 4.291
0.873 3.576
1.024 3.146
1.176 2.946
5.282 2.918
5.491 2.832
5.59 2.517
5.782 1.859
5.924 1.287
6.061 0.715
6.17 0.286
6.26 0.0

@ -1,20 +1,20 @@
; Raketenmodellbau Klima GmbH
; Official manufacturer thrust data - D9
; Created by Leo Nutz for OpenRocket,
; released into the Public Domain (3/2014)
D9 18 70 0-3-5-7-P 0.0161 0.0271 Klima
0.04 2.111
0.116 9.685
0.213 25.0
0.286 15.738
0.329 12.472
0.369 10.67
0.42 9.713
0.495 9.178
0.597 8.896
1.711 8.925
1.826 8.699
1.917 8.052
1.975 6.954
2.206 1.07
2.242 0.0
; Raketenmodellbau Klima GmbH
; Official manufacturer thrust data - D9
; Created by Leo Nutz for OpenRocket,
; released into the Public Domain (3/2014)
D9 18 70 0-3-5-7-P 0.0161 0.0271 Klima
0.04 2.111
0.116 9.685
0.213 25.0
0.286 15.738
0.329 12.472
0.369 10.67
0.42 9.713
0.495 9.178
0.597 8.896
1.711 8.925
1.826 8.699
1.917 8.052
1.975 6.954
2.206 1.07
2.242 0.0

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,171 +1,171 @@
#
# English base translation file
#
# Should you need to add new logical keys here is the proposed method
#
# className.ComponentType.componentName
#
#
# Text tokens within braces should not be translated, e.g.
# "The file '{filename}' exists."
# They are pieces that are inserted dynamically.
#
! Set to the name of the current translation file (used for debugging
purposes)
debug.currentFile = messages.properties
! RocketActions
RocketActions.checkbox.Donotaskmeagain = Yeniden Tekrarlama
RocketActions.lbl.Youcanchangedefop = Hatal\u0131 \u00c7al\u0131\u015fmay\u0131 De\u011fi\u015ftirebilirsin
in the preferences.
RocketActions.showConfirmDialog.lbl1 = Se\u00e7ili sim\u00fclasyonlar\u0131 silmek ister misiniz?
RocketActions.showConfirmDialog.lbl2 = <html><i>Bu \u00e7al\u0131\u015fma tamamlanmad\u0131.</i>
RocketActions.showConfirmDialog.title = Sim\u00fclasyonlar\u0131 Sil
RocketActions.DelCompAct.Delete = Sil
RocketActions.DelCompAct.ttip.Delete = Se\u00e7ili par\u00e7ay\u0131 sil.
RocketActions.DelSimuAct.Delete = Sil
RocketActions.DelSimuAct.ttip.Delete = Se\u00e7ili sim\u00fclasyonu sil.
RocketActions.DelAct.Delete = Sil
RocketActions.DelAct.ttip.Delete = Se\u00e7ilen par\u00e7ay\u0131 ya da sim\u00fclasyonu sil
RocketActions.CutAction.Cut = Kes
RocketActions.CutAction.ttip.Cut = Kes bu par\u00e7ay\u0131 yada sim\u00fclasyonun
haf\u0131zadan ve kald\u0131r bu tasar\u0131mdan
RocketActions.CopyAct.Copy = Kopyala
RocketActions.CopyAct.ttip.Copy = Bu par\u00e7ay\u0131 kopyala (ve altpar\u00e7alar\u0131)
haf\u0131zaya
RocketActions.PasteAct.Paste = Yap\u0131\u015ft\u0131r
RocketActions.PasteAct.ttip.Paste = Yap\u0131\u015ft\u0131r par\u00e7ay\u0131 ya da simulasyonu haf\u0131za \u00fczerinden
tasar\u0131ma do\u011fru.
RocketActions.EditAct.Edit = D\u00fczenle
RocketActions.EditAct.ttip.Edit = Se\u00e7ilmi\u015f par\u00e7ay\u0131 d\u00fczenle .
RocketActions.NewStageAct.Newstage = Yeni A\u015fama
RocketActions.NewStageAct.ttip.Newstage = Yeni bir roket tasar\u0131m\u0131 ekle
RocketActions.ActBoosterstage = Yard\u0131mc\u0131/Y\u00fckseltici A\u015fama
RocketActions.MoveUpAct.Moveup = Yukar\u0131 \u00c7\u0131kar
RocketActions.MoveUpAct.ttip.Moveup = Yukar\u0131ya do\u011fru bu par\u00e7ay\u0131 haraket ettir.
RocketActions.MoveDownAct.Movedown = A\u015fa\u011f\u0131ya \u0130ndir
RocketActions.MoveDownAct.ttip.Movedown = A\u015fa\u011f\u0131ya do\u011fru bu par\u00e7ay\u0131 haraket
ettir.
! RocketPanel
RocketPanel.FigTypeAct.SideView = Yandan G\u00f6r\u00fcn\u00fc\u015f
RocketPanel.FigTypeAct.BackView = Arkadan G\u00f6r\u00fcn\u00fc\u015f
RocketPanel.FigTypeAct.Figure3D = 3D Resimlendirme
RocketPanel.FigTypeAct.Finished = 3D Bitmi\u015f
RocketPanel.FigTypeAct.Unfinished = 3D Bitmemi\u015f
RocketPanel.lbl.Flightcfg = U\u00e7u\u015f Bi\u00e7imi/Konumu:
RocketPanel.lbl.infoMessage = <html>Click to select &nbsp;&nbsp; Shift+Click
to select other &nbsp;&nbsp; Double-click to edit &nbsp;&nbsp; Click+drag to
move
RocketPanel.lbl.ViewType = G\u00f6r\u00fcn\u00fc\u015f \u015eekli:
! BasicFrame
BasicFrame.tab.Rocketdesign = Roket Tasar\u0131m\u0131
BasicFrame.tab.Flightconfig = Motorlar & Bi\u00e7imleri
BasicFrame.tab.Flightsim = U\u00e7u\u015f Sim\u00fclasyonlar\u0131
BasicFrame.title.Addnewcomp = Yeni par\u00e7a ekle
BasicFrame.dlg.lbl1 = Tasar\u0131m '
BasicFrame.dlg.lbl2 = ' Kaydedilmemi\u015f.
BasicFrame.dlg.lbl3 = Kaydetmek ister misiniz?
BasicFrame.dlg.title = Tasar\u0131m Kaydedilmedi
BasicFrame.StageName.Sustainer = Devam Et
BasicFrame.WarningDialog.txt1 = Problemler a\u00e7\u0131l\u0131rken d\u00fczenleniyor
BasicFrame.WarningDialog.txt2 = Baz\u0131 tasar\u0131m par\u00e7alar\u0131 d\u00fczg\u00fcnce
y\u00fcklenemedi.
BasicFrame.WarningDialog.title = Dosya a\u00e7\u0131l\u0131rken Tehlike
! General error messages used in multiple contexts
error.fileExists.title = File exists
error.fileExists.desc = File '{filename}' exists. \u00dczerine yazmak ister misiniz?
error.writing.title = Hata Dosya Yaz\u0131l\u0131rken
error.writing.desc = Bir hata dosya yaz\u0131l\u0131rken ortaya \u00e7\u0131kt\u0131:
Configuration.lbl.override = Bu durum baz\u0131 u\u00e7u\u015f bi\u00e7imlerinde ge\u00e7ersizdir.
! Labels used in buttons of dialog windows
# TODO: Rename these to "btn.xxx"
button.ok = Tamam
button.cancel = \u00c7\u0131k\u0131\u015f
button.close = Kapat
! Common labels used in buttons of dialog windows
dlg.but.ok = Tamam
dlg.but.cancel = \u00c7\u0131k\u0131\u015f
dlg.but.close = Kapat
! General file type names
FileHelper.PDF_FILTER = PDF files (*.pdf)
FileHelper.ALL_DESIGNS_FILTER = All rocket designs (*.ork; *.rkt)
FileHelper.OPENROCKET_DESIGN_FILTER = OpenRocket designs (*.ork)
FileHelper.ROCKSIM_DESIGN_FILTER = RockSim designs (*.rkt)
FileHelper.OPEN_ROCKET_COMPONENT_FILTER = OpenRocket presets (*.orc)
FileHelper.IMAGES = Resim Dosyalar\u0131
! Diyolog Hakk\u0131nda
AboutDialog.lbl.version = Version
! The texts below provide additional credits for the translation maintainer
! - In AboutDialog.lbl.translation replace "English" with the current
language.
! - AboutDialog.lbl.translator is the translator / group name (may be empty)
! - AboutDialog.lbl.translatorWebsite is a URL to the translator / group
(may be empty)
! - AboutDialog.lbl.translatorIcon is the file name of an icon under
pix/translators/ (may be empty)
AboutDialog.lbl.translation = English translation by:Turkish
AboutDialog.lbl.translator =Batuhan Dereli
AboutDialog.lbl.translatorWebsite =www.batuhandereli.com
AboutDialog.lbl.translatorIcon =
! Yaz\u0131c\u0131
PrintDialog.title = Yazd\u0131r yada \u00c7\u0131kart
PrintDialog.but.previewAndPrint = \u00c7\u0131kt\u0131 \u00d6ncesi Bak & Yaz
PrintDialog.checkbox.showByStage = Par\u00e7a G\u00f6ster
PrintDialog.lbl.selectElements = \u0130\u00e7eren gruplar\u0131 se\u00e7:
printdlg.but.saveaspdf = Kaydet PDF Olarak
printdlg.but.preview = \u00d6nceki
printdlg.but.settings = Ayarlar
PrintDialog.error.preview.title = \u00d6nceki g\u00f6r\u00fcnt\u00fc ula\u015f\u0131lmaz
PrintDialog.error.preview.desc1 = Pdf g\u00f6r\u00fcnt\u00fc ula\u015f\u0131lmaz.
PrintDialog.error.preview.desc2 = L\u00fctfen kullan "Pdf Olarak Kaydet" i\u00e7eren
ayarlardan.
!PrintSettingsDialog
PrintSettingsDialog.title = Yaz\u0131c\u0131 Ayarlar\u0131
PrintSettingsDialog.lbl.Templatefillcolor = Kal\u0131p Renkli Doldur:
PrintSettingsDialog.lbl.Templatebordercolor = Kal\u0131b\u0131 S\u0131n\u0131rl\u0131 Doldur:
PrintSettingsDialog.lbl.Papersize = Ka\u011f\u0131t Boyutu:
PrintSettingsDialog.lbl.Paperorientation = Ka\u011f\u0131t Hizalama:
PrintSettingsDialog.but.Reset = Yeniden Ba\u015flat
PrintSettingsDialog.but.Close = Kapat
! Bug Report dialog
bugreport.dlg.title = Hata Raporu
bugreport.dlg.but.Sendbugreport = Hata Raporu G\u00f6nder
bugreport.dlg.but.Sendbugreport.Ttip = Atomatik olarak hata raporu g\u00f6nder OPEN ROCKET
geli\u015ftiricilerine.
bugreport.dlg.successmsg1 = Hata raporu sorunsuz yolland\u0131.
bugreport.dlg.successmsg2 = Te\u015fekk\u00fcrler sizin sayenizde OPENROCKET daha iyi geli\u015ficek!
bugreport.dlg.successmsg3 = Hata Raporu G\u00f6nderildi
bugreport.dlg.connectedInternet = <html>E\u011fer internet ba\u011flant\u0131n varsa,
basit\u00e7e t\u0131klay\u0131p<em>Hata Raporu G\u00f6nder</em>.
bugreport.dlg.otherwise = Ba\u015fka \u015fekilde,adrese yollay\u0131n:
bugreport.lbl.Theinformation = Genel hata raporlar\u0131hakk\u0131nda bilgi i\u00e7eriyor.Emin de\u011filsen ve
hislerinden \u00f6t\u00fcr\u00fc koyuyorsan hata raporunu koyma .
bugreport.dlg.failedmsg1 = OpenRocket hata raporunu g\u00f6ndermek i\u00e7in uygun de\u011fil:
bugreport.dlg.failedmsg2 = L\u00fctfen manual bir yolla g\u00f6nder
bugreport.dlg.failedmsg3 = Hata raporu g\u00f6nderiliyor
bugreport.reportDialog.txt = <html><b> OpenRocket i\u00e7erisindeki hatalar\u0131
form doldurarak yollayabilirsiniz.</b><br>Hatta hatalar\u0131 dosyalay\u0131p internet sitesi
\u00fczerinde proje sayfas\u0131na koyabilirsin.
bugreport.reportDialog.txt2 = <html><b>L\u00fctfen belirtiniz tam olarak nas\u0131l bir beklentiniz vard\u0131</b>
bugreport.dlg.provideDescription = L\u00fctfen Hatay\u0131 ilk ne zaman rastlad\u0131n\u0131z tam olarak a\u00e7\u0131klay\u0131n\u0131z
#
# English base translation file
#
# Should you need to add new logical keys here is the proposed method
#
# className.ComponentType.componentName
#
#
# Text tokens within braces should not be translated, e.g.
# "The file '{filename}' exists."
# They are pieces that are inserted dynamically.
#
! Set to the name of the current translation file (used for debugging
purposes)
debug.currentFile = messages.properties
! RocketActions
RocketActions.checkbox.Donotaskmeagain = Yeniden Tekrarlama
RocketActions.lbl.Youcanchangedefop = Hatal\u0131 \u00c7al\u0131\u015fmay\u0131 De\u011fi\u015ftirebilirsin
in the preferences.
RocketActions.showConfirmDialog.lbl1 = Se\u00e7ili sim\u00fclasyonlar\u0131 silmek ister misiniz?
RocketActions.showConfirmDialog.lbl2 = <html><i>Bu \u00e7al\u0131\u015fma tamamlanmad\u0131.</i>
RocketActions.showConfirmDialog.title = Sim\u00fclasyonlar\u0131 Sil
RocketActions.DelCompAct.Delete = Sil
RocketActions.DelCompAct.ttip.Delete = Se\u00e7ili par\u00e7ay\u0131 sil.
RocketActions.DelSimuAct.Delete = Sil
RocketActions.DelSimuAct.ttip.Delete = Se\u00e7ili sim\u00fclasyonu sil.
RocketActions.DelAct.Delete = Sil
RocketActions.DelAct.ttip.Delete = Se\u00e7ilen par\u00e7ay\u0131 ya da sim\u00fclasyonu sil
RocketActions.CutAction.Cut = Kes
RocketActions.CutAction.ttip.Cut = Kes bu par\u00e7ay\u0131 yada sim\u00fclasyonun
haf\u0131zadan ve kald\u0131r bu tasar\u0131mdan
RocketActions.CopyAct.Copy = Kopyala
RocketActions.CopyAct.ttip.Copy = Bu par\u00e7ay\u0131 kopyala (ve altpar\u00e7alar\u0131)
haf\u0131zaya
RocketActions.PasteAct.Paste = Yap\u0131\u015ft\u0131r
RocketActions.PasteAct.ttip.Paste = Yap\u0131\u015ft\u0131r par\u00e7ay\u0131 ya da simulasyonu haf\u0131za \u00fczerinden
tasar\u0131ma do\u011fru.
RocketActions.EditAct.Edit = D\u00fczenle
RocketActions.EditAct.ttip.Edit = Se\u00e7ilmi\u015f par\u00e7ay\u0131 d\u00fczenle .
RocketActions.NewStageAct.Newstage = Yeni A\u015fama
RocketActions.NewStageAct.ttip.Newstage = Yeni bir roket tasar\u0131m\u0131 ekle
RocketActions.ActBoosterstage = Yard\u0131mc\u0131/Y\u00fckseltici A\u015fama
RocketActions.MoveUpAct.Moveup = Yukar\u0131 \u00c7\u0131kar
RocketActions.MoveUpAct.ttip.Moveup = Yukar\u0131ya do\u011fru bu par\u00e7ay\u0131 haraket ettir.
RocketActions.MoveDownAct.Movedown = A\u015fa\u011f\u0131ya \u0130ndir
RocketActions.MoveDownAct.ttip.Movedown = A\u015fa\u011f\u0131ya do\u011fru bu par\u00e7ay\u0131 haraket
ettir.
! RocketPanel
RocketPanel.FigTypeAct.SideView = Yandan G\u00f6r\u00fcn\u00fc\u015f
RocketPanel.FigTypeAct.BackView = Arkadan G\u00f6r\u00fcn\u00fc\u015f
RocketPanel.FigTypeAct.Figure3D = 3D Resimlendirme
RocketPanel.FigTypeAct.Finished = 3D Bitmi\u015f
RocketPanel.FigTypeAct.Unfinished = 3D Bitmemi\u015f
RocketPanel.lbl.Flightcfg = U\u00e7u\u015f Bi\u00e7imi/Konumu:
RocketPanel.lbl.infoMessage = <html>Click to select &nbsp;&nbsp; Shift+Click
to select other &nbsp;&nbsp; Double-click to edit &nbsp;&nbsp; Click+drag to
move
RocketPanel.lbl.ViewType = G\u00f6r\u00fcn\u00fc\u015f \u015eekli:
! BasicFrame
BasicFrame.tab.Rocketdesign = Roket Tasar\u0131m\u0131
BasicFrame.tab.Flightconfig = Motorlar & Bi\u00e7imleri
BasicFrame.tab.Flightsim = U\u00e7u\u015f Sim\u00fclasyonlar\u0131
BasicFrame.title.Addnewcomp = Yeni par\u00e7a ekle
BasicFrame.dlg.lbl1 = Tasar\u0131m '
BasicFrame.dlg.lbl2 = ' Kaydedilmemi\u015f.
BasicFrame.dlg.lbl3 = Kaydetmek ister misiniz?
BasicFrame.dlg.title = Tasar\u0131m Kaydedilmedi
BasicFrame.StageName.Sustainer = Devam Et
BasicFrame.WarningDialog.txt1 = Problemler a\u00e7\u0131l\u0131rken d\u00fczenleniyor
BasicFrame.WarningDialog.txt2 = Baz\u0131 tasar\u0131m par\u00e7alar\u0131 d\u00fczg\u00fcnce
y\u00fcklenemedi.
BasicFrame.WarningDialog.title = Dosya a\u00e7\u0131l\u0131rken Tehlike
! General error messages used in multiple contexts
error.fileExists.title = File exists
error.fileExists.desc = File '{filename}' exists. \u00dczerine yazmak ister misiniz?
error.writing.title = Hata Dosya Yaz\u0131l\u0131rken
error.writing.desc = Bir hata dosya yaz\u0131l\u0131rken ortaya \u00e7\u0131kt\u0131:
Configuration.lbl.override = Bu durum baz\u0131 u\u00e7u\u015f bi\u00e7imlerinde ge\u00e7ersizdir.
! Labels used in buttons of dialog windows
# TODO: Rename these to "btn.xxx"
button.ok = Tamam
button.cancel = \u00c7\u0131k\u0131\u015f
button.close = Kapat
! Common labels used in buttons of dialog windows
dlg.but.ok = Tamam
dlg.but.cancel = \u00c7\u0131k\u0131\u015f
dlg.but.close = Kapat
! General file type names
FileHelper.PDF_FILTER = PDF files (*.pdf)
FileHelper.ALL_DESIGNS_FILTER = All rocket designs (*.ork; *.rkt)
FileHelper.OPENROCKET_DESIGN_FILTER = OpenRocket designs (*.ork)
FileHelper.ROCKSIM_DESIGN_FILTER = RockSim designs (*.rkt)
FileHelper.OPEN_ROCKET_COMPONENT_FILTER = OpenRocket presets (*.orc)
FileHelper.IMAGES = Resim Dosyalar\u0131
! Diyolog Hakk\u0131nda
AboutDialog.lbl.version = Version
! The texts below provide additional credits for the translation maintainer
! - In AboutDialog.lbl.translation replace "English" with the current
language.
! - AboutDialog.lbl.translator is the translator / group name (may be empty)
! - AboutDialog.lbl.translatorWebsite is a URL to the translator / group
(may be empty)
! - AboutDialog.lbl.translatorIcon is the file name of an icon under
pix/translators/ (may be empty)
AboutDialog.lbl.translation = English translation by:Turkish
AboutDialog.lbl.translator =Batuhan Dereli
AboutDialog.lbl.translatorWebsite =www.batuhandereli.com
AboutDialog.lbl.translatorIcon =
! Yaz\u0131c\u0131
PrintDialog.title = Yazd\u0131r yada \u00c7\u0131kart
PrintDialog.but.previewAndPrint = \u00c7\u0131kt\u0131 \u00d6ncesi Bak & Yaz
PrintDialog.checkbox.showByStage = Par\u00e7a G\u00f6ster
PrintDialog.lbl.selectElements = \u0130\u00e7eren gruplar\u0131 se\u00e7:
printdlg.but.saveaspdf = Kaydet PDF Olarak
printdlg.but.preview = \u00d6nceki
printdlg.but.settings = Ayarlar
PrintDialog.error.preview.title = \u00d6nceki g\u00f6r\u00fcnt\u00fc ula\u015f\u0131lmaz
PrintDialog.error.preview.desc1 = Pdf g\u00f6r\u00fcnt\u00fc ula\u015f\u0131lmaz.
PrintDialog.error.preview.desc2 = L\u00fctfen kullan "Pdf Olarak Kaydet" i\u00e7eren
ayarlardan.
!PrintSettingsDialog
PrintSettingsDialog.title = Yaz\u0131c\u0131 Ayarlar\u0131
PrintSettingsDialog.lbl.Templatefillcolor = Kal\u0131p Renkli Doldur:
PrintSettingsDialog.lbl.Templatebordercolor = Kal\u0131b\u0131 S\u0131n\u0131rl\u0131 Doldur:
PrintSettingsDialog.lbl.Papersize = Ka\u011f\u0131t Boyutu:
PrintSettingsDialog.lbl.Paperorientation = Ka\u011f\u0131t Hizalama:
PrintSettingsDialog.but.Reset = Yeniden Ba\u015flat
PrintSettingsDialog.but.Close = Kapat
! Bug Report dialog
bugreport.dlg.title = Hata Raporu
bugreport.dlg.but.Sendbugreport = Hata Raporu G\u00f6nder
bugreport.dlg.but.Sendbugreport.Ttip = Atomatik olarak hata raporu g\u00f6nder OPEN ROCKET
geli\u015ftiricilerine.
bugreport.dlg.successmsg1 = Hata raporu sorunsuz yolland\u0131.
bugreport.dlg.successmsg2 = Te\u015fekk\u00fcrler sizin sayenizde OPENROCKET daha iyi geli\u015ficek!
bugreport.dlg.successmsg3 = Hata Raporu G\u00f6nderildi
bugreport.dlg.connectedInternet = <html>E\u011fer internet ba\u011flant\u0131n varsa,
basit\u00e7e t\u0131klay\u0131p<em>Hata Raporu G\u00f6nder</em>.
bugreport.dlg.otherwise = Ba\u015fka \u015fekilde,adrese yollay\u0131n:
bugreport.lbl.Theinformation = Genel hata raporlar\u0131hakk\u0131nda bilgi i\u00e7eriyor.Emin de\u011filsen ve
hislerinden \u00f6t\u00fcr\u00fc koyuyorsan hata raporunu koyma .
bugreport.dlg.failedmsg1 = OpenRocket hata raporunu g\u00f6ndermek i\u00e7in uygun de\u011fil:
bugreport.dlg.failedmsg2 = L\u00fctfen manual bir yolla g\u00f6nder
bugreport.dlg.failedmsg3 = Hata raporu g\u00f6nderiliyor
bugreport.reportDialog.txt = <html><b> OpenRocket i\u00e7erisindeki hatalar\u0131
form doldurarak yollayabilirsiniz.</b><br>Hatta hatalar\u0131 dosyalay\u0131p internet sitesi
\u00fczerinde proje sayfas\u0131na koyabilirsin.
bugreport.reportDialog.txt2 = <html><b>L\u00fctfen belirtiniz tam olarak nas\u0131l bir beklentiniz vard\u0131</b>
bugreport.dlg.provideDescription = L\u00fctfen Hatay\u0131 ilk ne zaman rastlad\u0131n\u0131z tam olarak a\u00e7\u0131klay\u0131n\u0131z
bugreport.dlg.provideDescription.title = Hata tan\u0131m\u0131 kayboluyor

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

@ -6,9 +6,6 @@
# arguments.
#
#该脚本用于运行由Eclipse从bin/目录编译的OpenRocket版本。你可以提供Java
# 参数和OpenRocket参数。
JAVAOPTS=""
while echo "$1" | grep -q "^-" ; do

@ -1,3 +1,3 @@
Manifest-Version: 1.0
Main-Class: startup.net.sf.openrocket.SwingStartup
Main-Class: net.sf.openrocket.startup.SwingStartup

@ -52,8 +52,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
}
// 创建一个新的BarrowmanCalculator对象。
@Override
public BarrowmanCalculator newInstance() {
return new BarrowmanCalculator();
@ -63,7 +62,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
/**
* Calculate the CP according to the extended Barrowman method.
*/
// 方法的作用是计算飞行器的重心位置Center of Pressure, CP
@Override
public Coordinate getCP(FlightConfiguration configuration, FlightConditions conditions,
WarningSet warnings) {
@ -73,7 +71,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
}
// 这个方法的作用是进行飞行器的力学分析,计算飞行器各组件的气动力,并返回一个包含各组件气动力信息的映射。
@Override
public Map<RocketComponent, AerodynamicForces> getForceAnalysis(FlightConfiguration configuration,
FlightConditions conditions,
@ -136,9 +134,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
return finalMap;
}
// 这个方法的作用是计算飞行器组件的气动力分析。
// 它接受飞行器的配置信息configuration、飞行条件conds、当前组件comp、组件实例映射instances、每个组件的气动力信息映射
// eachForces、总装配体的气动力信息映射assemblyForces和警告信息warnings作为参数。
private AerodynamicForces calculateForceAnalysis( FlightConfiguration configuration,
FlightConditions conds,
RocketComponent comp,
@ -184,7 +179,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
return assemblyForces.get(comp);
}
// 它的作用是计算火箭飞行时的空气动力学力Aerodynamic Forces并将结果保存在AerodynamicForces对象中。
@Override
public AerodynamicForces getAerodynamicForces(FlightConfiguration configuration,
FlightConditions conditions, WarningSet warnings) {
@ -215,7 +209,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
}
// 它的作用是计算火箭组件在非轴向方向上的空气动力学力Non-Axial Forces
private AerodynamicForces calculateComponentNonAxialForces( FlightConditions conditions,
RocketComponent comp,
RocketComponentCalc calcObj,
@ -249,7 +242,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
/**
* Perform the actual CP calculation.
*/
// 它的作用是计算火箭在非轴向方向上的空气动力学力Non-Axial Forces
private AerodynamicForces calculateNonAxialForces(FlightConfiguration configuration, FlightConditions conditions, WarningSet warnings) {
checkCache(configuration);
@ -286,9 +278,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
return assemblyForces;
}
// 这个方法的作用是检查火箭的几何结构是否符合要求,并根据检查结果生成警告信息。
// 方法接受三个参数FlightConfiguration对象表示火箭的飞行配置RocketComponent对象表示火箭组件的根节点WarningSet对象
// 用于存储警告信息。
@Override
public void checkGeometry(FlightConfiguration configuration, final RocketComponent treeRoot, WarningSet warnings ){
Queue<RocketComponent> queue = new LinkedList<>();
@ -414,8 +403,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
* @param warningSet Set to handle warnings
* @return friction drag for entire rocket
*/
// 这个方法的作用是计算整个火箭受到空气摩擦力的阻力系数。
// 它使用了火箭的配置和飞行条件,以及一些参数(如雷诺数、粗糙度修正系数等)来计算火箭的摩擦阻力系数。
private double calculateFrictionCD(FlightConfiguration configuration, FlightConditions conditions,
Map<RocketComponent, AerodynamicForces> forceMap, WarningSet warningSet) {
@ -534,7 +521,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
* @param conditions Flight conditions taken into account
* @return Reynolds Number
*/
// 这个方法的作用是计算雷诺数Reynolds Number
private double calculateReynoldsNumber(FlightConfiguration configuration, FlightConditions conditions) {
return conditions.getVelocity() * configuration.getLengthAerodynamic() /
conditions.getAtmosphericConditions().getKinematicViscosity();
@ -546,10 +532,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
*
* return skin friction coefficient
*/
// 这个方法的作用是计算皮肤摩擦系数skin friction coefficient。在火箭飞行中空气的粘性会产生阻力而皮肤摩擦系数描述
// 了空气在火箭表面摩擦阻力的大小。
// 该方法接受三个参数FlightConfiguration对象configuration、火箭的马赫数mach、雷诺数Re。根据这些参数方法通过
// 一系列的条件判断和计算来确定皮肤摩擦系数的值,并返回结果。
private double calculateFrictionCoefficient(FlightConfiguration configuration, double mach, double Re) {
double Cf;
double c1 = 1.0, c2 = 1.0;
@ -640,9 +622,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
* @param mach
* @return roughness correction
**/
// 这个方法的作用是计算火箭表面粗糙度修正系数roughness correction
// 在实际火箭飞行中,火箭表面可能存在一些粗糙度,这会影响阻力和其他性能参数的计算。
// 该方法接受一个参数火箭的马赫数mach。根据马赫数该方法通过一系列的条件判断和计算来确定粗糙度修正系数的值并返回结果。
private double calculateRoughnessCorrection(double mach) {
double c1, c2;
@ -670,10 +650,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
* @param warningSet all current warnings
* @return
*/
// 这个方法的作用是计算火箭在飞行过程中由于气压所产生的阻力系数drag coefficient
// 该方法接受四个参数火箭的配置信息configuration、飞行条件conditions、气动力学力量映射forceMap和警告集合
// warningSet。其中配置信息包括了火箭各个部件的尺寸、重量等信息飞行条件包括了火箭的高度、速度、气压等信息
// 气动力学力量映射用于记录每个火箭部件受到的气动力学力量;警告集合用于记录计算过程中出现的任何警告。
private double calculatePressureCD(FlightConfiguration configuration, FlightConditions conditions,
Map<RocketComponent, AerodynamicForces> forceMap, WarningSet warningSet) {
@ -751,8 +727,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
* @param warnings all current warnings
* @return
*/
// 这个方法的作用是计算由底部引起的阻力系数drag coefficient
// 该方法通过考虑飞行条件、火箭配置和火箭组件的几何参数来计算底部的阻力系数。
private double calculateBaseCD(FlightConfiguration configuration, FlightConditions conditions,
Map<RocketComponent, AerodynamicForces> forceMap, WarningSet warnings) {
@ -827,7 +801,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
* @param m Mach number for calculation
* @return Stagnation CD
*/
// 这个方法的作用是根据给定的速度Mach数计算静止状态下的阻力系数stagnation drag coefficient
public static double calculateStagnationCD(double m) {
double pressure;
if (m <= 1) {
@ -844,8 +817,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
* @param m Mach number for calculation
* @return Base CD
*/
// 这个方法的作用是计算基础阻力系数base drag coefficient以便在火箭的空气动力学计算中使用。
// 基础阻力系数是计算火箭总阻力的重要组成部分之一。
public static double calculateBaseCD(double m) {
if (m <= 1) {
return 0.12 + 0.13 * m * m;
@ -881,7 +852,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
* @param cd
* @return
*/
// 这个方法的作用是根据给定的飞行条件和总阻力系数,计算轴向阻力系数。
private double calculateAxialCD(FlightConditions conditions, double cd) {
double aoa = MathUtil.clamp(conditions.getAOA(), 0, Math.PI);
double mul;
@ -905,21 +875,18 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
/**
* add together CD overrides for active components
*
*
* @param configuration Rocket configuration
* @param conditions Flight conditions taken into account
* @param forceMap
* @param warningSet all current warnings
* @return
*/
// 该方法的作用是计算活动组件的阻力系数覆盖值的总和,并将覆盖值应用到相应的力信息中,用于后续的火箭飞行性能计算和模拟。
// 方法中的参数包括 configuration火箭配置、conditions飞行条件、eachMap单个组件的力信息映射、assemblyMap
// (组件装配的力信息映射)和 warningSet当前的警告集合
private double calculateOverrideCD(FlightConfiguration configuration, FlightConditions conditions,
Map<RocketComponent, AerodynamicForces> eachMap,
Map<RocketComponent, AerodynamicForces> assemblyMap,
Map<RocketComponent, AerodynamicForces> assemblyMap,
WarningSet warningSet) {
if (calcMap == null)
buildCalcMap(configuration);
@ -954,8 +921,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
* @param conditions flight conditions in consideration
* @param total acting aerodynamic forces
*/
// 该方法的作用是计算火箭在飞行中受到的阻尼力矩,以考虑火箭的飞行状态、姿态和速度等因素,用于后续的火箭飞行性能计算和模拟。
// 方法中的参数包括 configuration火箭配置、conditions飞行条件和 total作用于火箭的总气动力
private void calculateDampingMoments(FlightConfiguration configuration, FlightConditions conditions,
AerodynamicForces total) {
@ -978,8 +943,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
total.setYawDampingMoment(MathUtil.sign(yawRate) * yawDampingMomentMagnitude);
}
// 该方法的作用是计算火箭在飞行中的阻尼系数的倍数,以考虑火箭的飞行状态、姿态和速度等因素对阻尼力的影响。
// 具体而言,该方法根据火箭的配置、飞行条件和重心位置等参数计算出一个阻尼系数的倍数,用于后续的火箭飞行性能计算和模拟。
private double getDampingMultiplier(FlightConfiguration configuration, FlightConditions conditions,
double cgx) {
if (cacheDiameter < 0) {
@ -1023,8 +986,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
//////// The calculator map
// 该方法用于清空气动参数缓存并重置计算器映射和火箭直径、长度等参数。
@Override
protected void voidAerodynamicCache() {
super.voidAerodynamicCache();
@ -1034,8 +996,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
cacheLength = -1;
}
// 该方法用于构建计算器映射 calcMap对于每个气动部件和组装部件创建一个 RocketComponentCalc 对象并将其与对应的
// RocketComponent 对象一起存储在计算器映射 calcMap 中。
private void buildCalcMap(FlightConfiguration configuration) {
calcMap = new HashMap<>();
@ -1049,8 +1010,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
calcMap.put(comp, calcObj );
}
}
// 该方法用于获取计算器的模组 ID
@Override
public int getModID() {
// Only cached data is stored, return constant mod ID

@ -1,23 +1,23 @@
package net.sf.openrocket.database.motor;
import java.util.List;
import net.sf.openrocket.motor.Motor;
public interface MotorDatabase {
/**
* Return all motors in the database matching a search criteria. Any search criteria that
* is null or NaN is ignored.
*
* @param type the motor type, or null.
* @param manufacturer the manufacturer, or null.
* @param designation the designation, or null.
* @param diameter the diameter, or NaN.
* @param length the length, or NaN.
* @return a list of all the matching motors.
*/
public List<? extends Motor> findMotors(String digest, Motor.Type type,
String manufacturer, String designation, double diameter,
double length);
}
package net.sf.openrocket.database.motor;
import java.util.List;
import net.sf.openrocket.motor.Motor;
public interface MotorDatabase {
/**
* Return all motors in the database matching a search criteria. Any search criteria that
* is null or NaN is ignored.
*
* @param type the motor type, or null.
* @param manufacturer the manufacturer, or null.
* @param designation the designation, or null.
* @param diameter the diameter, or NaN.
* @param length the length, or NaN.
* @return a list of all the matching motors.
*/
public List<? extends Motor> findMotors(String digest, Motor.Type type,
String manufacturer, String designation, double diameter,
double length);
}

@ -1,8 +1,8 @@
package net.sf.openrocket.document;
import java.util.EventListener;
public interface UndoRedoListener extends EventListener {
public void setAllValues();
}
package net.sf.openrocket.document;
import java.util.EventListener;
public interface UndoRedoListener extends EventListener {
public void setAllValues();
}

@ -1,176 +1,176 @@
package net.sf.openrocket.models.wind;
import java.util.Random;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.util.PinkNoise;
/**
* A wind simulator that generates wind speed as pink noise from a specified average wind speed
* and standard deviance. Currently the wind is always directed in the direction of the negative
* X-axis. The simulated wind is unaffected by the altitude.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public class PinkNoiseWindModel implements WindModel {
/** Random value with which to XOR the random seed value */
private static final int SEED_RANDOMIZATION = 0x7343AA03;
/** Pink noise alpha parameter. */
private static final double ALPHA = 5.0 / 3.0;
/** Number of poles to use in the pink noise IIR filter. */
private static final int POLES = 2;
/** The standard deviation of the generated pink noise with the specified number of poles. */
private static final double STDDEV = 2.252;
/** Time difference between random samples. */
private static final double DELTA_T = 0.05;
private double average = 0;
private double direction = Math.PI / 2; // this is an East wind
private double standardDeviation = 0;
private final int seed;
private PinkNoise randomSource = null;
private double time1;
private double value1, value2;
/**
* Construct a new wind simulation with a specific seed value.
* @param seed the seed value.
*/
public PinkNoiseWindModel(int seed) {
this.seed = seed ^ SEED_RANDOMIZATION;
}
/**
* Return the average wind speed.
*
* @return the average wind speed.
*/
public double getAverage() {
return average;
}
/**
* Set the average wind speed. This method will also modify the
* standard deviation such that the turbulence intensity remains constant.
*
* @param average the average wind speed to set
*/
public void setAverage(double average) {
double intensity = getTurbulenceIntensity();
this.average = Math.max(average, 0);
setTurbulenceIntensity(intensity);
}
public void setDirection(double direction) {
this.direction = direction;
}
public double getDirection() {
return this.direction;
}
/**
* Return the standard deviation from the average wind speed.
*
* @return the standard deviation of the wind speed
*/
public double getStandardDeviation() {
return standardDeviation;
}
/**
* Set the standard deviation of the average wind speed.
*
* @param standardDeviation the standardDeviation to set
*/
public void setStandardDeviation(double standardDeviation) {
this.standardDeviation = Math.max(standardDeviation, 0);
}
/**
* Return the turbulence intensity (standard deviation / average).
*
* @return the turbulence intensity
*/
public double getTurbulenceIntensity() {
if (MathUtil.equals(average, 0)) {
if (MathUtil.equals(standardDeviation, 0))
return 0;
else
return 1000;
}
return standardDeviation / average;
}
/**
* Set the standard deviation to match the turbulence intensity.
*
* @param intensity the turbulence intensity
*/
public void setTurbulenceIntensity(double intensity) {
setStandardDeviation(intensity * average);
}
@Override
public Coordinate getWindVelocity(double time, double altitude) {
if (time < 0) {
throw new IllegalArgumentException("Requesting wind speed at t=" + time);
}
if (randomSource == null) {
randomSource = new PinkNoise(ALPHA, POLES, new Random(seed));
time1 = 0;
value1 = randomSource.nextValue();
value2 = randomSource.nextValue();
}
if (time < time1) {
reset();
return getWindVelocity(time, altitude);
}
while (time1 + DELTA_T < time) {
value1 = value2;
value2 = randomSource.nextValue();
time1 += DELTA_T;
}
double a = (time - time1) / DELTA_T;
double speed = average + (value1 * (1 - a) + value2 * a) * standardDeviation / STDDEV;
return new Coordinate(speed * Math.sin(direction), speed * Math.cos(direction), 0);
}
private void reset() {
randomSource = null;
}
@Override
public int getModID() {
return (int) (average * 1000 + standardDeviation);
}
}
package net.sf.openrocket.models.wind;
import java.util.Random;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.util.PinkNoise;
/**
* A wind simulator that generates wind speed as pink noise from a specified average wind speed
* and standard deviance. Currently the wind is always directed in the direction of the negative
* X-axis. The simulated wind is unaffected by the altitude.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public class PinkNoiseWindModel implements WindModel {
/** Random value with which to XOR the random seed value */
private static final int SEED_RANDOMIZATION = 0x7343AA03;
/** Pink noise alpha parameter. */
private static final double ALPHA = 5.0 / 3.0;
/** Number of poles to use in the pink noise IIR filter. */
private static final int POLES = 2;
/** The standard deviation of the generated pink noise with the specified number of poles. */
private static final double STDDEV = 2.252;
/** Time difference between random samples. */
private static final double DELTA_T = 0.05;
private double average = 0;
private double direction = Math.PI / 2; // this is an East wind
private double standardDeviation = 0;
private final int seed;
private PinkNoise randomSource = null;
private double time1;
private double value1, value2;
/**
* Construct a new wind simulation with a specific seed value.
* @param seed the seed value.
*/
public PinkNoiseWindModel(int seed) {
this.seed = seed ^ SEED_RANDOMIZATION;
}
/**
* Return the average wind speed.
*
* @return the average wind speed.
*/
public double getAverage() {
return average;
}
/**
* Set the average wind speed. This method will also modify the
* standard deviation such that the turbulence intensity remains constant.
*
* @param average the average wind speed to set
*/
public void setAverage(double average) {
double intensity = getTurbulenceIntensity();
this.average = Math.max(average, 0);
setTurbulenceIntensity(intensity);
}
public void setDirection(double direction) {
this.direction = direction;
}
public double getDirection() {
return this.direction;
}
/**
* Return the standard deviation from the average wind speed.
*
* @return the standard deviation of the wind speed
*/
public double getStandardDeviation() {
return standardDeviation;
}
/**
* Set the standard deviation of the average wind speed.
*
* @param standardDeviation the standardDeviation to set
*/
public void setStandardDeviation(double standardDeviation) {
this.standardDeviation = Math.max(standardDeviation, 0);
}
/**
* Return the turbulence intensity (standard deviation / average).
*
* @return the turbulence intensity
*/
public double getTurbulenceIntensity() {
if (MathUtil.equals(average, 0)) {
if (MathUtil.equals(standardDeviation, 0))
return 0;
else
return 1000;
}
return standardDeviation / average;
}
/**
* Set the standard deviation to match the turbulence intensity.
*
* @param intensity the turbulence intensity
*/
public void setTurbulenceIntensity(double intensity) {
setStandardDeviation(intensity * average);
}
@Override
public Coordinate getWindVelocity(double time, double altitude) {
if (time < 0) {
throw new IllegalArgumentException("Requesting wind speed at t=" + time);
}
if (randomSource == null) {
randomSource = new PinkNoise(ALPHA, POLES, new Random(seed));
time1 = 0;
value1 = randomSource.nextValue();
value2 = randomSource.nextValue();
}
if (time < time1) {
reset();
return getWindVelocity(time, altitude);
}
while (time1 + DELTA_T < time) {
value1 = value2;
value2 = randomSource.nextValue();
time1 += DELTA_T;
}
double a = (time - time1) / DELTA_T;
double speed = average + (value1 * (1 - a) + value2 * a) * standardDeviation / STDDEV;
return new Coordinate(speed * Math.sin(direction), speed * Math.cos(direction), 0);
}
private void reset() {
randomSource = null;
}
@Override
public int getModID() {
return (int) (average * 1000 + standardDeviation);
}
}

@ -1,6 +1,5 @@
package net.sf.openrocket.motor;
// 发动机接口
public interface Motor {
/**
@ -9,14 +8,9 @@ public interface Motor {
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public enum Type {
// 四种类型的发动机
// 单次使用的固体推进剂发动机
SINGLE("Single-use", "Single-use solid propellant motor"),
// 可重新装填的固体推进剂发动机
RELOAD("Reloadable", "Reloadable solid propellant motor"),
// 混合动力火箭发动机
HYBRID("Hybrid", "Hybrid rocket motor engine"),
// 未知的发动机
SINGLE("Single-use", "Single-use solid propellant motor"),
RELOAD("Reloadable", "Reloadable solid propellant motor"),
HYBRID("Hybrid", "Hybrid rocket motor engine"),
UNKNOWN("Unknown", "Unknown motor type");
@ -50,13 +44,9 @@ public interface Motor {
return name;
}
}
// 几种时间
// 发动机不存在时的时间,是一个无效值
public static final double PSEUDO_TIME_EMPTY = Double.NaN;
// 火箭处于发射时刻的时间
public static final double PSEUDO_TIME_LAUNCH = 0.0;
// 发动机燃烧结束的时间,设置为无穷大,说明发动机会一直燃烧
public static final double PSEUDO_TIME_BURNOUT = Double.MAX_VALUE;
@ -64,7 +54,6 @@ public interface Motor {
* Ejection charge delay value signifying a "plugged" motor with no ejection charge.
* The value is that of <code>Double.POSITIVE_INFINITY</code>.
*/
// 没有引爆炸药时发动机的燃烧时间,设置为无穷大
public static final double PLUGGED_DELAY = Double.POSITIVE_INFINITY;

@ -60,8 +60,7 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
private double unitRotationalInertia;
private double unitLongitudinalInertia;
// 内部类用于构建ThrustCurveMotor对象并设置该对象的各个属性。
public static class Builder {
ThrustCurveMotor motor = new ThrustCurveMotor();
@ -262,7 +261,6 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
*
* @return the manufacturer
*/
// 用于获取该发动机的制造商manufacturer对象。
public Manufacturer getManufacturer() {
return manufacturer;
}
@ -272,7 +270,6 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
* Return the array of time points for this thrust curve.
* @return an array of time points where the thrust is sampled
*/
// 方法返回推力曲线中采样的时间点数组,表示在这些时间点上进行了推力采样。
public double[] getTimePoints() {
return time.clone();
}
@ -287,8 +284,6 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
* @param is time after motor ignition, in seconds
* @return a pseudo index to this motor's data.
*/
// 方法根据给定的时间点相对于发动机点火后的时间计算伪索引pseudo index
// 伪索引由两部分组成:整数部分是数组中的简单索引,小数部分是[0,1]之间的值,用于在给定索引和下一个索引之间进行插值。
protected double getPseudoIndex( final double motorTime ){
if(( time.length == 0 )||( 0 > motorTime )){
return Double.NaN;
@ -298,9 +293,7 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
final double fraction = getIndexFraction( motorTime, lowerIndex );
return ((double)lowerIndex)+fraction;
}
// 方法根据给定的时间点找到对应的索引。
// 它通过迭代比较给定时间点和时间数组中的元素,直到找到最后一个小于等于给定时间点的元素的索引。
private int getIndex( final double motorTime ){
int lowerBoundIndex=0;
int upperBoundIndex=0;
@ -311,9 +304,7 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
return lowerBoundIndex;
}
// 方法根据给定的时间点和索引计算索引的小数部分。
// 它使用给定索引和下一个索引之间的时间差来计算给定时间点在两个索引之间的位置,并返回该位置与索引之间的比例。
private double getIndexFraction( final double motorTime, final int index ){
final double SNAP_DISTANCE = 0.0001;
@ -341,8 +332,7 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
return indexFraction;
}
}
// 方法用于计算在给定时间范围内的平均推力。
@Override
public double getAverageThrust( final double startTime, final double endTime ) {
@ -384,8 +374,7 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
return impulse / (endTime - startTime);
}
// 方法用于获取给定时间时刻的推力值。
@Override
public double getThrust( final double motorTime ){
double pseudoIndex = getPseudoIndex( motorTime );
@ -393,8 +382,7 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
final double thrustAtTime= ThrustCurveMotor.interpolateAtIndex( thrust, pseudoIndex);
return thrustAtTime;
}
// 方法用于获取给定时间时刻的重心位置。
@Override
public double getCMx( final double motorTime ){
double pseudoIndex = getPseudoIndex( motorTime );
@ -402,17 +390,15 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
}
// 方法返回火箭外形信息的字符串表示。
public String getCaseInfo() {
return caseInfo;
}
// 方法返回一个CaseInfo枚举类型表示火箭外形信息。
public CaseInfo getCaseInfoEnum() {
return CaseInfo.parse(caseInfo);
}
// 方法返回一个CaseInfo数组表示与当前火箭外形兼容的其他外形。
public CaseInfo[] getCompatibleCases() {
CaseInfo myCase = getCaseInfoEnum();
if (myCase == null) {
@ -420,13 +406,12 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
}
return myCase.getCompatibleCases();
}
// 方法返回推进剂信息的字符串表示。
public String getPropellantInfo() {
return propellantInfo;
}
// 方法返回火箭初始质量。
public double getInitialMass() {
return initialMass;
}
@ -436,7 +421,6 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
* Returns the array of thrust points for this thrust curve.
* @return an array of thrust samples
*/
// 方法返回推力数组的副本,即所有推力样本的数组。
public double[] getThrustPoints() {
return thrust.clone();
}
@ -448,8 +432,7 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
// public double[] getCGxPoints() {
// return cgx;
// }
// 方法返回重心位置数组,即所有重心样本的数组。
public Coordinate[] getCGPoints(){
return cg;
}
@ -466,7 +449,6 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
* Return a list of standard delays defined for this motor.
* @return a list of standard delays
*/
// 返回定义在该电动机中的标准延迟时间数组。
public double[] getStandardDelays() {
return delays.clone();
}
@ -477,121 +459,100 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
* NOTE: In most cases you want to examine the motor type of the ThrustCurveMotorSet,
* not the ThrustCurveMotor itself.
*/
// 返回电动机的类型(Type)
@Override
public Type getMotorType() {
return type;
}
// 返回电动机的单位纵向惯性。
public double getUnitLongitudinalInertia() {
return this.unitLongitudinalInertia;
}
// 返回电动机的单位旋转惯性。
public double getUnitRotationalInertia() {
return this.unitRotationalInertia;
}
// 实现接口RocketMotor的方法返回电动机的单位惯性矩Ixx。
@Override
public double getUnitIxx() {
return this.unitRotationalInertia;
}
// 实现接口RocketMotor的方法返回电动机的单位惯性矩Iyy。
@Override
public double getUnitIyy() {
return this.unitLongitudinalInertia;
}
// 实现接口RocketMotor的方法返回电动机的单位惯性矩Izz。
@Override
public double getUnitIzz(){
return this.unitLongitudinalInertia;
}
// 返回电动机的代码。
@Override
public String getCode() {
return code;
}
// 返回电动机的通用名称。
@Override
public String getCommonName() {
return commonName;
}
// 返回带有延迟时间的电动机通用名称。
@Override
public String getCommonName(double delay) {
return commonName + "-" + getDelayString(delay);
}
// 返回电动机的指定名称。
@Override
public String getDesignation() {
return designation;
}
// 返回带有延迟时间的电动机指定名称。
@Override
public String getDesignation(double delay) {
return designation + "-" + getDelayString(delay);
}
// 返回电动机的描述。
@Override
public String getDescription() {
return description;
}
// 返回电动机的直径。
@Override
public double getDiameter() {
return diameter;
}
// 返回电动机的长度。
@Override
public double getLength() {
return length;
}
// 返回发射时的重心位置。
@Override
public double getLaunchCGx() {
return cg[0].x;//cgx[0];
}
// 返回燃烧结束时的重心位置。
@Override
public double getBurnoutCGx() {
return cg[cg.length - 1].x;// cgx[ cg.length - 1];
}
// 返回发射时的质量。
@Override
public double getLaunchMass() {
return cg[0].weight;//mass[0];
}
// 返回燃烧结束时的质量。
@Override
public double getBurnoutMass() {
return cg[cg.length-1].weight; //mass[mass.length - 1];
}
// 返回电动机的燃烧时间。
@Override
public double getBurnTime() {
return time[time.length-1];
}
// 这个方法的作用是在给定的数组中进行插值计算。它接受一个包含数值的数组和一个伪索引pseudoIndex作为参数并返回在该伪
// 索引处进行插值计算后得到的结果。
private static double interpolateAtIndex( final double[] values, final double pseudoIndex ){
final double SNAP_TOLERANCE = 0.0001;
@ -625,34 +586,29 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
* @param motorTime
* @return the time at requested time
*/
// 该方法用于获取给定伪时间对应的真实时间。
public double getTime( final double motorTime ){
final double pseudoIndex = getPseudoIndex( motorTime);
final double foundTime = ThrustCurveMotor.interpolateAtIndex( this.time, pseudoIndex);
return foundTime;
}
// 该方法用于获取给定时间时刻的总质量,包括推进剂质量和火箭结构质量。
@Override
public double getTotalMass( final double motorTime){
final double pseudoIndex = getPseudoIndex( motorTime);
return interpolateCenterOfMassAtIndex( pseudoIndex).weight;
}
// 该方法用于获取推进剂的质量,即初始质量减去燃尽质量。
public double getPropellantMass(){
return (getLaunchMass() - getBurnoutMass());
}
// 该方法用于获取给定时间时刻的推进剂质量。
@Override
public double getPropellantMass( final Double motorTime){
final double pseudoIndex = getPseudoIndex( motorTime);
final double totalMass = interpolateCenterOfMassAtIndex( pseudoIndex).weight;
return totalMass - this.getBurnoutMass();
}
// 该方法用于在给定伪索引位置进行重心位置的插值计算。
protected Coordinate interpolateCenterOfMassAtIndex( final double pseudoIndex ){
final double SNAP_TOLERANCE = 0.0001;
@ -674,48 +630,40 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
return lowerValue.add( upperValue );
}
// 该方法用于获取数据数组的大小,即时间数组的长度。
public int getDataSize() {
return this.time.length;
}
// 返回电动机的燃烧时间估计值。
@Override
public double getBurnTimeEstimate() {
return burnTimeEstimate;
}
// 返回电动机的平均推力估计值。
@Override
public double getAverageThrustEstimate() {
return averageThrust;
}
// 返回电动机的最大推力估计值。
@Override
public double getMaxThrustEstimate() {
return maxThrust;
}
// 返回电动机的总脉冲估计值。
@Override
public double getTotalImpulseEstimate() {
return totalImpulse;
}
// 返回电动机的信息摘要。
@Override
public String getDigest() {
return digest;
}
// 返回电动机的燃烧结束时间。
public double getCutOffTime() {
return time[time.length - 1];
}
// 返回电动机数据是否可用。
public boolean isAvailable() {
return available;
}
@ -723,9 +671,6 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
/**
* Compute the general statistics of this motor.
*/
// 这个方法的作用是计算火箭发动机的一些统计数据。具体来说,它计算了以下几个参数:
// 最大推力maxThrust燃烧开始时间burnStart和燃烧结束时间burnEnd燃烧时间估计burnTimeEstimate总冲量
// totalImpulse和平均推力averageThrust
private void computeStatistics() {
// Maximum thrust
@ -826,7 +771,6 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
* @param delay the delay time.
* @return the <code>String</code> representation.
*/
// 将延迟时间转换为字符串表示。如果延迟时间为PLUGGED_DELAY一个常量则返回字符串"P"。
public static String getDelayString(double delay) {
return getDelayString(delay, "P");
}
@ -839,7 +783,6 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
* @param plugged the return value if there is no ejection charge.
* @return the String representation.
*/
// 将延迟时间转换为字符串表示。如果延迟时间为PLUGGED_DELAY则返回参数"plugged"指定的字符串。
public static String getDelayString(double delay, String plugged) {
if (delay == PLUGGED_DELAY)
return plugged;
@ -854,13 +797,12 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
*
* @return return the size of the data arrays
*/
// 返回测量推力、重心位置、质量和时间等数据点的数量。
public int getSampleSize(){
return time.length;
}
// 重写了Comparable接口中的compareTo方法用于比较两个ThrustCurveMotor对象的大小。
@Override
public int compareTo(ThrustCurveMotor other) {

@ -12,47 +12,33 @@ import net.sf.openrocket.util.*;
/**
* radiuslength
* Rocket body tube component. Has only two parameters, a radius and length.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMount, Coaxial, InsideColorComponent {
// 用于进行翻译和本地化操作
private static final Translator trans = Application.getTranslator();
// 机身管的外半径
private double outerRadius = 0;
// 是否自动选择机身管的半径
private boolean autoRadius = false; // Radius chosen automatically based on parent component
// 自动选择半径的参考组件
private SymmetricComponent refComp = null; // Reference component that is used for the autoRadius
// 机身管的悬挑长度,当改变内半径时,厚度也会相应地改变
// When changing the inner radius, thickness is modified
private double overhang = 0;
// 机身管是否作为安装支架
private boolean isActingMount = false;
// 与机身管相关联的发动机配置集合
private MotorConfigurationSet motors;
// 处理机身管内部颜色的组件
private InsideColorComponentHandler insideColorComponentHandler = new InsideColorComponentHandler(this);
/************ 构造函数 ************/
public BodyTube() {
this(8 * DEFAULT_RADIUS, DEFAULT_RADIUS);
this.autoRadius = true;
}
// 根构造函数,总是被其他构造函数调用
// root ctor. Always called by other ctors
public BodyTube(double length, double radius) {
super();
this.outerRadius = Math.max(radius, 0);
@ -74,21 +60,17 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
}
/************ 组件参数的 get/set 方法 ************/
/**
*
* @return
*/
/************ Get/set component parameter methods ************/
@Override
public ComponentPreset.Type getPresetType() {
return ComponentPreset.Type.BODY_TUBE;
}
/**
*
* @return double
* Return the outer radius of the body tube.
*
* @return the outside radius of the tube
*/
@Override
public double getOuterRadius() {
@ -116,21 +98,20 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
return outerRadius;
}
// 该方法的作用是返回手动输入的机身管道外半径outer radius而不是自动获取的半径值。
// 在方法中,直接返回存储在 outerRadius 变量中的外半径值。由于该值是手动输入的,因此不受自动半径计算的影响。
/**
*
* @return double
* Return the outer radius that was manually entered, so not the value that the component received from automatic
* outer radius.
*/
public double getOuterRadiusNoAutomatic() {
return outerRadius;
}
/**
*
* @param radius
* Set the outer radius of the body tube. If the radius is less than the wall thickness,
* the wall thickness is decreased accordingly of the value of the radius.
* This method sets the automatic radius off.
*
* @param radius the outside radius in standard units
*/
@Override
public void setOuterRadius(double radius) {
@ -151,19 +132,18 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
clearPreset();
}
/**
*
* @return boolean
* Returns whether the radius is selected automatically or not.
* Returns false also in case automatic radius selection is not possible.
*/
public boolean isOuterRadiusAutomatic() {
return autoRadius;
}
/**
*
* @param auto
* Sets whether the radius is selected automatically or not.
*/
public void setOuterRadiusAutomatic(boolean auto) {
for (RocketComponent listener : configListeners) {
@ -180,31 +160,16 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
clearPreset();
}
/**
* 使
* @return boolean 使
*/
@Override
public boolean usesPreviousCompAutomatic() {
return isOuterRadiusAutomatic() && refComp == getPreviousSymmetricComponent();
}
/**
* 使
* @return boolean 使
*/
@Override
public boolean usesNextCompAutomatic() {
return isOuterRadiusAutomatic() && refComp == getNextSymmetricComponent();
}
/**
*
* @param preset
*/
@Override
protected void loadFromPreset(ComponentPreset preset) {
this.autoRadius = false;
@ -221,54 +186,29 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
/**
*
* @return double
*/
@Override
public double getAftRadius() {
return getOuterRadius();
}
/**
*
* @return double
*/
@Override
public double getForeRadius() {
return getOuterRadius();
}
/**
* 使
* @return boolean 使
*/
@Override
public boolean isAftRadiusAutomatic() {
return isOuterRadiusAutomatic();
}
/**
* 使
* @return boolean 使
*/
@Override
public boolean isForeRadiusAutomatic() {
return isOuterRadiusAutomatic();
}
// 该方法的作用是获取机身管道的前端自动选择半径。
/**
*
* @return double
*/
@Override
protected double getFrontAutoRadius() {
if (isOuterRadiusAutomatic()) {
@ -282,12 +222,7 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
}
return getOuterRadius();
}
/**
*
* @return double
*/
@Override
protected double getRearAutoRadius() {
if (isOuterRadiusAutomatic()) {
@ -305,24 +240,14 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
// 该方法的作用是获取机身管道的内半径。
/**
*
* @return double
*/
@Override
public double getInnerRadius() {
if (filled)
return 0;
return Math.max(getOuterRadius() - thickness, 0);
}
/**
*
* @param r
*/
@Override
public void setInnerRadius(double r) {
for (RocketComponent listener : configListeners) {
@ -336,14 +261,9 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
// 该方法的作用是返回机身管道组件的名称,即 "BodyTube.BodyTube"。
// 在方法中,调用了 trans.get() 方法来获取对应的翻译字符串。trans 是一个 TranslationMap 对象,用于存储 OpenRocket 界面
// 上的所有翻译字符串。get() 方法通过传入的键值 "BodyTube.BodyTube" 来获取对应的翻译字符串,并将其作为方法的返回值。
/**
*
* @return String
* Return the component name.
*/
@Override
public String getComponentName() {
@ -352,24 +272,19 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
}
/************ 组件计算部分 ***********/
/************ Component calculations ***********/
// From SymmetricComponent
/**
* x
* @param x x
* @return double
* Returns the outer radius at the position x. This returns the same value as getOuterRadius().
*/
@Override
public double getRadius(double x) {
return getOuterRadius();
}
/**
* x
* @param x
* @return double
* Returns the inner radius at the position x. If the tube is filled, returns always zero.
*/
@Override
public double getInnerRadius(double x) {
@ -379,20 +294,17 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
return Math.max(getOuterRadius() - thickness, 0);
}
/**
*
* @return Coordinate
* Returns the body tube's center of gravity.
*/
@Override
public Coordinate getComponentCG() {
return new Coordinate(length / 2, 0, 0, getComponentMass());
}
/**
*
* @return double
* Returns the body tube's volume.
*/
@Override
public double getComponentVolume() {
@ -403,22 +315,13 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
return getFilledVolume(r, length) - getFilledVolume(getInnerRadius(0), length);
}
/**
*
* @return double
*/
@Override
public double getLongitudinalUnitInertia() {
// 1/12 * (3 * (r2^2 + r1^2) + h^2)
return (3 * (MathUtil.pow2(getOuterRadius()) + MathUtil.pow2(getInnerRadius())) + MathUtil.pow2(getLength())) / 12;
}
/**
*
* @return double
*/
@Override
public double getRotationalUnitInertia() {
// 1/2 * (r1^2 + r2^2)
@ -428,25 +331,13 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
// 用于计算圆柱体体积的辅助函数。
/**
*
* @param r
* @param l
* @return double
* Helper function for cylinder volume.
*/
private static double getFilledVolume(double r, double l) {
return Math.PI * r * r * l;
}
/**
*
* @return
*/
public BoundingBox getInstanceBoundingBox(){
BoundingBox instanceBounds = new BoundingBox();
@ -459,12 +350,13 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
return instanceBounds;
}
/**
*
* @param type
* @return
*/
/**
* Check whether the given type can be added to this component. BodyTubes allow any
* InternalComponents or ExternalComponents, excluding BodyComponents, to be added.
*
* @param type The RocketComponent class type to add.
* @return Whether such a component can be added.
*/
@Override
public boolean isCompatible(Class<? extends RocketComponent> type) {
if (ParallelStage.class.isAssignableFrom(type))
@ -480,44 +372,23 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
return false;
}
/**
*
* @return
*/
//////////////// Motor mount /////////////////
@Override
public MotorConfiguration getDefaultMotorConfig(){
return this.motors.getDefault();
}
/**
*
* @return
*/
@Override
public MotorConfigurationSet getMotorConfigurationSet() {
return this.motors;
}
/**
* ID
* @param fcid ID
* @return
*/
@Override
public MotorConfiguration getMotorConfig( final FlightConfigurationId fcid){
return this.motors.get(fcid);
}
// 这个方法的主要功能是设置机身管的火箭发动机配置,并在需要时进行一些额外的校验和操作,以确保配置的正确性和一致性。
/**
*
* @param newMotorConfig
* @param fcid ID
*/
@Override
public void setMotorConfig(MotorConfiguration newMotorConfig, FlightConfigurationId fcid){
for (RocketComponent listener : configListeners) {
@ -543,42 +414,22 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
this.isActingMount=true;
}
/**
*
* @return
*/
@Override
public Iterator<MotorConfiguration> getMotorIterator(){
return this.motors.iterator();
}
/**
* ID
* @param fcid ID
*/
@Override
public void reset( final FlightConfigurationId fcid){
this.motors.reset(fcid);
}
/**
* IDID
* @param oldConfigId ID
* @param newConfigId ID
*/
@Override
public void copyFlightConfiguration(FlightConfigurationId oldConfigId, FlightConfigurationId newConfigId) {
motors.copyFlightConfiguration(oldConfigId, newConfigId);
}
/**
*
* @param _active
*/
@Override
public void setMotorMount(boolean _active){
for (RocketComponent listener : configListeners) {
@ -593,63 +444,34 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
fireComponentChangeEvent(ComponentChangeEvent.MOTOR_CHANGE);
}
/**
*
* @return
*/
@Override
public boolean isMotorMount(){
return this.isActingMount;
}
/**
*
* @return
*/
@Override
public boolean hasMotor() {
// the default MotorInstance is the EMPTY_INSTANCE.
// If the class contains more instances, at least one will have motors.
return ( 1 < this.motors.size());
}
/**
*
* @return
*/
@Override
public int getMotorCount() {
return this.getClusterConfiguration().getClusterCount();
}
/**
*
* @return
*/
@Override
public double getMotorMountDiameter() {
return getInnerRadius() * 2;
}
/**
*
* @return
*/
@Override
public double getMotorOverhang() {
return overhang;
}
/**
*
* @param overhang
*/
@Override
public void setMotorOverhang(double overhang) {
for (RocketComponent listener : configListeners) {
@ -664,12 +486,7 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
/**
*
* @param id ID
* @return
*/
@Override
public Coordinate getMotorPosition(FlightConfigurationId id) {
Motor motor = this.motors.get(id).getMotor();
@ -680,21 +497,11 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
return new Coordinate(this.getLength() - motor.getLength() + this.getMotorOverhang());
}
/**
*
* @return
*/
@Override
public String toMotorDebug(){
return this.motors.toDebug();
}
/**
* BodyTubeID
* @return BodyTube
*/
@Override
protected RocketComponent copyWithOriginalID() {
BodyTube copy = (BodyTube) super.copyWithOriginalID();
@ -703,42 +510,22 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
return copy;
}
/**
* BodyTube
* @return
*/
@Override
public ClusterConfiguration getClusterConfiguration() {
return ClusterConfiguration.SINGLE;
}
/**
* BodyTube
* @return
*/
@Override
public InsideColorComponentHandler getInsideColorComponentHandler() {
return this.insideColorComponentHandler;
}
/**
* BodyTube
* @param handler
*/
@Override
public void setInsideColorComponentHandler(InsideColorComponentHandler handler) {
this.insideColorComponentHandler = handler;
}
/**
* BodyTube
* @param listener
* @return
*/
@Override
public boolean addConfigListener(RocketComponent listener) {
boolean success = super.addConfigListener(listener);
@ -750,11 +537,6 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
return false;
}
/**
* BodyTube
* @param listener
*/
@Override
public void removeConfigListener(RocketComponent listener) {
super.removeConfigListener(listener);
@ -764,10 +546,6 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
}
}
/**
* BodyTube
*/
@Override
public void clearConfigListeners() {
super.clearConfigListeners();

@ -21,29 +21,23 @@ import net.sf.openrocket.startup.Application;
import net.sf.openrocket.rocketcomponent.Transition.Shape;
public abstract class FinSet extends ExternalComponent implements AxialPositionable, BoxBounded, RingInstanceable, InsideColorComponent {
// 记录日志的Logger对象
private static final Logger log = LoggerFactory.getLogger(FinSet.class);
// 处理国际化的Translator对象
private static final Translator trans = Application.getTranslator();
// 鳍片的最大允许倾角
/**
* Maximum allowed cant of fins.
*/
public static final double MAX_CANT_RADIANS = (15.0 * Math.PI / 180);
// 根几何中允许的最大根点数量
/**
* Maximum number of root points in the root geometry.
*/
private static final int MAX_ROOT_DIVISIONS = 100;
// 低分辨率模式下的根点数量限制
private static final int MAX_ROOT_DIVISIONS_LOW_RES = MAX_ROOT_DIVISIONS / 5;
public void setOverrideMass() {
}
/**
* CrossSection
*/
public enum CrossSection {
//// Square
SQUARE(trans.get("FinSet.CrossSection.SQUARE"), 1.00),
@ -70,103 +64,101 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
}
}
// 鳍片数量
/**
* Number of fins.
*/
private int finCount = 3;
// 鳍片旋转的增量
/**
* Rotation about the x-axis by 2*PI/fins.
*/
private Transformation finRotationIncrement = Transformation.IDENTITY;
// 旋转角度的计算方法
/**
* Rotation angle of the first fin. Zero corresponds to the positive y-axis.
*/
private AngleMethod angleMethod = AngleMethod.RELATIVE;
// 第一个鳍片的旋转角度偏移量
private double firstFinOffsetRadians = 0;
// 基本的旋转变换
private Transformation baseRotation = Transformation.IDENTITY; // initially, rotate by 0 degrees.
// 鳍片的斜度角度
/**
* Cant angle of fins.
*/
private double cantRadians = 0;
// 斜度旋转变换
/* Cached value: */
private Transformation cantRotation = null;
// 鳍片尺寸半径的计算方法
// fixed to body surface...
final private RadiusMethod radiusMethod = RadiusMethod.SURFACE;
// 鳍片的厚度
/**
* Thickness of the fins.
*/
protected double thickness = 0.003;
// 鳍片的横截面形状
/**
* The cross-section shape of the fins.
*/
private CrossSection crossSection = CrossSection.SQUARE;
// 鳍片连接翼根的最小面积
/*
* Fin tab properties.
*/
private static final double minimumTabArea = 1e-8;
// 连接翼根的翼根高度
private double tabHeight = 0;
// 连接翼根的长度
private double tabLength = 0.05;
// 连接翼根相对于鳍片根部的位置
// this is always measured from the root-lead point.
private double tabPosition = 0.0;
// 计算连接翼根偏移量的方法
private AxialMethod tabOffsetMethod = AxialMethod.MIDDLE;
// 连接翼根的偏移量
private double tabOffset = 0.;
// 鳍片的填充材料
/*
* Fin fillet properties
*/
private Material filletMaterial;
// 圆角的半径
private double filletRadius = 0;
// ==== Cached Values ====
// Fin area does not include fin tabs, CG does.
// 单个鳍片的投影面积
// planform area of one side of a single fin
private double singlePlanformArea = Double.NaN;
// 整个鳍片的体积
private double totalVolume = Double.NaN;
// 鳍片的质心坐标
private Coordinate centerOfMass = Coordinate.NaN;
// 处理鳍片内部颜色组件的操作
private InsideColorComponentHandler insideColorComponentHandler = new InsideColorComponentHandler(this);
/**
*
* 使
* New FinSet with given number of fins and given base rotation angle.
* Sets the component relative position to POSITION_RELATIVE_BOTTOM,
* i.e. fins are positioned at the bottom of the parent component.
*/
public FinSet() {
super( AxialMethod.BOTTOM);
this.filletMaterial = Application.getPreferences().getDefaultComponentMaterial(this.getClass(), Material.Type.BULK);
super.displayOrder_side = 4; // 组件在2D侧视图中的显示顺序
super.displayOrder_back = 4; // 组件在2D背视图中的显示顺序
super.displayOrder_side = 4; // Order for displaying the component in the 2D side view
super.displayOrder_back = 4; // Order for displaying the component in the 2D back view
}
/**
*
* @return
*/
@Override
public boolean isAfter(){
return false;
}
/**
*
* @return
* Return the number of fins in the set.
* @return The number of fins.
*/
public int getFinCount() {
return finCount;
}
/**
*
* @param n
* Sets the number of fins in the set.
* @param n The number of fins, greater of equal to one.
*/
public void setFinCount(int n) {
for (RocketComponent listener : configListeners) {
@ -187,35 +179,27 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
/**
*
* @return
*/
public Transformation getFinRotationTransformation() {
return finRotationIncrement;
}
/**
*
* @return
*/
@Override
public double getBoundingRadius(){
return 0.;
}
/**
*
* @return
* Gets the base rotation amount of the first fin.
* @return The base rotation amount.
*/
public double getBaseRotation() {
return getAngleOffset();
}
/**
*
* @param r
* Sets the base rotation amount of the first fin.
* @param r The base rotation in radians
*/
public void setBaseRotation(double r) {
for (RocketComponent listener : configListeners) {
@ -228,17 +212,15 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
}
/**
*
* @return
* @return angle current cant angle, in radians
*/
// 通过调用 getCantAngle() 方法,可以获取当前对象的 cant 角度值
public double getCantAngle() {
return cantRadians;
}
/**
*
* @param newCantRadians
*
* @param newCantRadians -- new cant angle, in radians
*/
public void setCantAngle(final double newCantRadians) {
for (RocketComponent listener : configListeners) {
@ -255,11 +237,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
fireComponentChangeEvent(ComponentChangeEvent.AERODYNAMIC_CHANGE);
}
/**
*
* @return
*/
public Transformation getCantRotation() {
if( null == cantRotation ) {
if (MathUtil.equals(this.cantRadians, 0)) {
@ -270,16 +247,11 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
}
return cantRotation;
}
/**
* FinSet
* @return
*/
public double getThickness() {
return thickness;
}
// 它的作用是设置 FinSet 对象的厚度,并触发相关的事件。
public void setThickness(double r) {
for (RocketComponent listener : configListeners) {
if (listener instanceof FinSet) {
@ -293,13 +265,11 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
// 它的作用是获取 FinSet 对象的横截面。
public CrossSection getCrossSection() {
return crossSection;
}
// 它的作用是设置 FinSet 对象的横截面,并触发相关的事件。
public void setCrossSection(CrossSection cs) {
for (RocketComponent listener : configListeners) {
if (listener instanceof FinSet) {
@ -312,8 +282,7 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
crossSection = cs;
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
// 它的作用是获取 FinSet 对象的襟翼高度。
public double getTabHeight() {
return tabHeight;
}
@ -334,10 +303,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
* from the fin root, at the reference point
*
*/
// 这段代码注释指明了下面的代码行涉及到设置鳍片从参考点处的基地到顶部的高度。通过调用该函数并传入适当的参数,可以设置鳍片
// 的高度,并进行边界检查以确保合理性。
// 它的作用是设置 FinSet 对象的襟翼高度,并触发相关的事件。
public void setTabHeight(final double newTabHeight) {
for (RocketComponent listener : configListeners) {
if (listener instanceof FinSet) {
@ -355,8 +320,7 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
}
// 它的作用是获取 FinSet 对象的襟翼长度。
public double getTabLength() {
return tabLength;
}
@ -364,7 +328,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
/**
* set tab length
*/
// 它的作用是设置 FinSet 对象的襟翼长度,并触发相关的事件。
public void setTabLength(final double lengthRequest) {
for (RocketComponent listener : configListeners) {
if (listener instanceof FinSet) {
@ -383,7 +346,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
}
// 它的作用是根据襟翼长度和偏移量更新襟翼位置。
public void updateTabPosition(){
this.tabPosition = this.tabOffsetMethod.getAsPosition(tabOffset, tabLength, length);
}
@ -393,7 +355,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
*
* @param offsetRequest new requested tab offset
*/
// 它的作用是设置襟翼的偏移量,并触发相关的事件。
public void setTabOffset( final double offsetRequest) {
for (RocketComponent listener : configListeners) {
if (listener instanceof FinSet) {
@ -406,8 +367,7 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
}
// 它的作用是获取当前 FinSet 对象使用的襟翼偏移量计算方法。
public AxialMethod getTabOffsetMethod() {
return tabOffsetMethod;
}
@ -416,7 +376,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
* the tab's positioning method variable does not change the internal representation --
* it is merely a lens through which other modules may view the tab's position.
*/
// 它的作用是设置襟翼的偏移量计算方法,并触发相关的事件。
public void setTabOffsetMethod(final AxialMethod newPositionMethod) {
for (RocketComponent listener : configListeners) {
if (listener instanceof FinSet) {
@ -433,14 +392,10 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
/**
* Return the tab front edge position from the front of the fin.
*/
// 返回鳍片前缘相对于鳍片前沿的位置。
// 它的作用是获取襟翼前缘的位置。
public double getTabFrontEdge() {
return tabPosition;
}
// 它的作用是根据指定的襟翼偏移量计算方法,获取当前 FinSet 对象襟翼的偏移量。
public double getTabOffset(AxialMethod method){
return method.getAsOffset(tabPosition, tabLength, length);
}
@ -452,12 +407,10 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
/**
* Return the tab trailing edge position *from the front of the fin*.
*/
// 这个方法的作用是返回从鳍前沿开始的制表尾缘位置。
public double getTabTrailingEdge() {
return tabPosition + tabLength;
}
// 这个方法的作用是验证鳍片制表位置是否在有效范围内,并在必要时进行修正。
public void validateFinTabPosition() {
//check front bounds:
if (tabPosition < 0) {
@ -469,8 +422,7 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
this.tabPosition = length;
}
}
// 这个方法的作用是验证鳍片制表长度是否在有效范围内,并在必要时进行修正。
public void validateFinTabLength() {
//System.err.println(String.format(" >> Fin Tab Length: %.6f @ %.6f", tabLength, tabOffset));
@ -488,7 +440,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
* Calculates the maximum height that the fin tabs can be, depending on the parent shape.
* @return maximum tab height value
*/
// 这个方法的作用是计算鳍片制表高度的最大值,具体取决于其所属的父形状。
public double getMaxTabHeight() {
Double radiusFront = getParentFrontRadius();
Double radiusTrailing = getParentTrailingRadius();
@ -502,7 +453,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
* Returns the radius of the parent at the front of the fin, or null if no parent is present.
* @param parent the fin's parent component
*/
// 这个方法的作用是返回鳍片前沿处父形状的半径值如果没有父形状则返回null。
public Double getParentFrontRadius(RocketComponent parent) {
if (parent instanceof SymmetricComponent) {
final Coordinate finFront = this.getFinFront();
@ -519,7 +469,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
/**
* Returns the radius of the parent at the front of the fin, or null if no parent is present.
*/
// 这个方法的作用是返回鳍片前沿处父形状的半径值或者如果没有父形状则返回null。
public Double getParentFrontRadius() {
return getParentFrontRadius(getParent());
}
@ -528,7 +477,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
* Returns the radius of the parent at the trailing edge of the fin, or null if no parent is present.
* @param parent the fin's parent component
*/
// 这个方法的作用是返回鳍片尾沿处父形状的半径值或者如果没有父形状则返回null。
public Double getParentTrailingRadius(RocketComponent parent) {
if (parent instanceof SymmetricComponent) {
final Coordinate finFront = this.getFinFront();
@ -545,7 +493,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
/**
* Returns the radius of the parent at the trailing edge of the fin, or null if no parent is present.
*/
// 这个方法的作用是返回鳍片尾沿处父形状的半径值或者如果没有父形状则返回null。
public Double getParentTrailingRadius() {
return getParentTrailingRadius(getParent());
}
@ -558,15 +505,13 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
*
* @return returns the one-sided air-exposed area of a single fin
*/
// 这个方法的作用是返回单个鳍片暴露在气流中(即外部面积)的面积。
public double getPlanformArea() {
if( Double.isNaN(singlePlanformArea) ){
calculateCM();
}
return this.singlePlanformArea;
}
// 这个方法的作用是返回组件的质量。
@Override
public double getComponentMass() {
if(this.centerOfMass.isNaN()){
@ -574,8 +519,7 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
}
return this.centerOfMass.weight;
}
// 这个方法的作用是返回组件的体积。
@Override
public double getComponentVolume() {
if(Double.isNaN(this.totalVolume)){
@ -590,8 +534,7 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
* the root chord leading edge and the Y-coordinate to the fin root chord.
*
* @return the Center-of-Mass coordinate of a single fin.
*/
// 这个方法的作用是返回单个鳍片的重心坐标。
*/
@Override
public Coordinate getComponentCG() {
if( centerOfMass.isNaN() ){
@ -601,7 +544,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
return centerOfMass;
}
// 这个方法的作用是计算鳍片的圆角截面的重心坐标和截面面积。
private static Coordinate calculateFilletCrossSection(final double filletRadius, final double bodyRadius){
final double hypotenuse = filletRadius + bodyRadius;
final double innerArcAngle = Math.asin(filletRadius / hypotenuse);
@ -638,9 +580,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
* 4. Multiply the remaining area by the length.
* 5. Return twice that since there is a fillet on each side of the fin.
*/
// 这段注释描述了根据给定的参数计算圆形凹槽体积的方法。
// 这个方法的作用是计算鳍片圆角的体积重心坐标。
protected Coordinate calculateFilletVolumeCentroid() {
if((null == this.parent) || (!SymmetricComponent.class.isAssignableFrom(this.parent.getClass()))){
return Coordinate.ZERO;
@ -696,7 +635,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
* @param points define a piece-wise line bounding the area.
* @return x,y,z => centroid of the area; weight => magnitude of the area
*/
// 这个方法用于计算给定边界线所围成的曲线下面积的重心和面积。
protected static Coordinate calculateCurveIntegral( final Coordinate[] points ){
Coordinate centroidSum = new Coordinate(0);
@ -740,7 +678,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
/**
* calculates the planform area-centroid of a single fin's tab:
*/
// 这个方法用于计算单个鳍片的鳍柄平面面积重心。
private Coordinate calculateTabCentroid(){
RocketComponent comp = getParent();
@ -764,8 +701,7 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
return calculateCurveIntegral( tabPoints );
}
// 这个方法用于将给定点数组fromRoot相对于鳍片中心线进行平移。
private Coordinate[] translateToCenterline( final Coordinate[] fromRoot) {
Coordinate finRoot = this.getFinFront();
@ -779,7 +715,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
*
* @return area centroid coordinates (weight is the area)
*/
// 这个方法用于计算单个鳍片的平面面积重心坐标和面积。
private Coordinate calculateSinglePlanformCentroid(){
final Coordinate finLead = getFinFront();
final double xFinTrail = finLead.x+getLength();
@ -803,8 +738,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
* @param c2 backward curve
* @return combined curve
*/
// 这个方法用于将两个点数组合并成一个点数组,其中第一个数组按照原来的顺序排列,而第二个数组则按照相反的顺序排列。在火箭设计
// 中使用。
private Coordinate[] combineCurves( final Coordinate[] c1, final Coordinate[] c2){
Coordinate[] combined = new Coordinate[ c1.length + c2.length];
@ -821,7 +754,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
// simply return a reversed copy of the source array
// 这个方法用于将给定的点数组进行反转,并返回一个反转后的副本。
public Coordinate[] reverse( Coordinate[] source){
Coordinate[] reverse = new Coordinate[ source.length ];
@ -849,7 +781,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
* 3. If there are multiple fins, the inertia is shifted to the center of the
* FinSet using the Parallel Axis Theorem
*/
// 这段代码是一个计算纵向单位惯性矩的方法。
@Override
public double getLongitudinalUnitInertia() {
if(Double.isNaN(this.singlePlanformArea)){
@ -901,7 +832,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
* 2. If there are multiple fins, shift the inertia axis to the center
* of the Finset.
*/
// 这段代码是用于计算鳍组的旋转单位惯性矩的方法。
@Override
public double getRotationalUnitInertia() {
if(Double.isNaN(this.singlePlanformArea)){
@ -932,7 +862,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
}
// 这个方法是用于获取鳍组实例的边界框bounding box。包括鳍的顶点和鳍的厚度对应的两个平面。
public BoundingBox getInstanceBoundingBox(){
final BoundingBox singleFinBounds = new BoundingBox();
@ -950,7 +879,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
*
* Currently the points are simply a rectangular box around the body tube.
*/
// 这个方法的作用是获取组件的边界坐标集合。它用于确定组件在三维空间中的边界范围,以便在建模和渲染过程中使用。
@Override
public Collection<Coordinate> getComponentBounds() {
Collection<Coordinate> bounds = new ArrayList<>(8);
@ -986,7 +914,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
return bounds;
}
// 这个方法的作用是在组件发生变化时更新相关属性。它是一个事件监听方法,当组件的气动属性或质量属性发生变化时被调用。
@Override
public void componentChanged(ComponentChangeEvent e) {
if (e.isAerodynamicChange() || e.isMassChange()) {
@ -1007,12 +934,10 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
*
* @return radius of the underlying BodyComponent or 0 if none exists.
*/
// 这个方法的作用是返回FinSet所在的BodyComponent的半径。当前只支持SymmetricComponents并且返回根弦起始点处的半径。
public double getBodyRadius() {
return getFinFront().y;
}
// 这个方法的作用是获取FinSet前端点leading edge在三维空间中的坐标。
public Coordinate getFinFront() {
final double xFinFront = this.getAxialFront();
final SymmetricComponent symmetricParent = (SymmetricComponent)this.getParent();
@ -1023,8 +948,7 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
return new Coordinate(xFinFront, yFinFront);
}
}
// 这个方法的作用是判断当前的FinSet对象是否允许包含子组件。
@Override
public boolean allowsChildren() {
return false;
@ -1035,20 +959,15 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
*
* @return <code>false</code>
*/
// 这个方法的作用是判断指定类型的RocketComponent是否与当前的FinSet对象兼容即是否可以将指定类型的RocketComponent附加
// 到当前的FinSet对象上。
@Override
public boolean isCompatible(Class<? extends RocketComponent> type) {
return false;
}
// 这个方法的作用是检查FinSet的Tab面积是否足够大以确保Tab可以有效地附着到机身上。
public boolean isTabTrivial(){
return ( FinSet.minimumTabArea > (getTabLength()*getTabHeight()));
}
// 这个方法的作用是判断FinSet是否与其父级对象直接相连并且父级对象是一个Transition类型的组件并且该Transition类型的
// 组件是圆锥形Shape.CONICAL
public boolean isRootStraight( ){
if( getParent() instanceof Transition){
return ((Transition) getParent()).getType() == Shape.CONICAL;
@ -1063,7 +982,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
*
* @return List of XY-coordinates.
*/
// 这个方法的作用是将给定的坐标点列表进行平移,返回平移后的新坐标点列表。
protected static Coordinate[] translatePoints( final Coordinate[] inp, final double x_delta , final double y_delta){
Coordinate[] returnPoints = new Coordinate[inp.length];
for( int index=0; index < inp.length; ++index){
@ -1079,7 +997,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
*
* @return List of XY-coordinates.
*/
// 这个方法的作用与之前的方法类似,也是将给定的坐标点列表进行平移,返回平移后的新坐标点列表。
protected static ArrayList<Coordinate> translatePoints( final ArrayList<Coordinate> inp, final Coordinate delta){
final ArrayList<Coordinate> returnPoints = new ArrayList<>();
returnPoints.ensureCapacity(inp.size());
@ -1099,7 +1016,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
*
* @return List of XY-coordinates.
*/
// 这个方法是一个抽象方法,用于获取定义单个鳍状物形状的坐标点列表。具体实现需要在子类中进行。
public abstract Coordinate[] getFinPoints();
/**
@ -1107,8 +1023,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
*
* @return points representing the fin-root points, relative to ( x: fin-front, y: centerline ) i.e. relto: fin Component reference point
*/
// 这个方法用于在轮廓设计视图中获取身体部分的坐标点。根据方法的注释,返回的坐标点表示鳍状物根部的点,相对于
// (x: fin-front, y: centerline) 的位置。也就是相对于鳍状物组件的参考点进行定位。
public Coordinate[] getRootPoints(final int maximumBodyDivisionCount) {
if( null == parent){
return new Coordinate[]{Coordinate.ZERO};
@ -1125,8 +1039,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
*
* @return points representing the fin-root points, relative to ( x: fin-front, y: centerline ) i.e. relto: fin Component reference point
*/
// 这个方法是一个重载方法,用于在轮廓设计视图中获取身体部分的坐标点。与之前的方法相比,这个方法省略了传入最大身体分割数的
// 参数,默认使用了一个常量 MAX_ROOT_DIVISIONS。
public Coordinate[] getRootPoints(){
return getRootPoints(MAX_ROOT_DIVISIONS);
}
@ -1136,8 +1048,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
*
* @return points representing the fin-root points, relative to ( x: fin-front, y: centerline ) i.e. relto: fin Component reference point
*/
// 这个方法用于计算物理特性和绘制鳍状物时获取鳍状物的安装点坐标。根据方法的注释,返回的坐标点表示鳍状物根部的点,相对于
// (x: fin-front, y: centerline) 的位置。也就是相对于鳍状物组件的参考点进行定位。
public Coordinate[] getMountPoints() {
if( null == parent){
return null;
@ -1156,8 +1066,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
*
* @return points representing the mount's points
*/
// 这是一个用于计算机身轮廓点的方法,根据传入的参数 xStart 和 xEnd以及父对象的半径函数计算出沿着机身前缘到后缘的一系列
// 点。这些点表示机身轮廓的形状。
private Coordinate[] getMountPoints(final double xStart, final double xEnd, final double xOffset, final double yOffset,
final int maximumBodyDivisionCount) {
if (parent == null) {
@ -1232,7 +1140,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
/**
* Return a list of coordinates defining the geometry of a single fin, including the parent's body points .
*/
// 这是一个用于获取包含鳍状物和机身根点的几何坐标列表的方法。
public Coordinate[] getFinPointsWithRoot() {
return combineCurves(getFinPoints(), getRootPoints());
}
@ -1243,7 +1150,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
* This low res version is for 3D rendering, as a too high resolution would cause clipping and invisible fin faces.
* This should at one point be solved by rendering the fin faces using triangulation, instead of how it's currently implemented.
*/
// 这是一个获取包含低分辨率机身根点的几何坐标列表的方法。
public Coordinate[] getFinPointsWithLowResRoot() {
return combineCurves(getFinPoints(), getRootPoints(MAX_ROOT_DIVISIONS_LOW_RES));
}
@ -1260,7 +1166,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
*
* @return List of XY-coordinates.
*/
// 这是一个获取单个鳍状物标签几何坐标列表的方法。
public Coordinate[] getTabPoints() {
if (MathUtil.equals(getTabHeight(), 0) ||
MathUtil.equals(getTabLength(), 0)){
@ -1295,8 +1200,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
*
* @return List of XY-coordinates.
*/
// 这是一个获取单个鳍状物标签低分辨率LowRes几何坐标列表的方法。
// 与之前的方法相比,这个方法主要用于在三维渲染中使用,并且采用低分辨率以避免剪裁和不可见的鳍状物面。
public Coordinate[] getTabPointsLowRes() {
if (MathUtil.equals(getTabHeight(), 0) ||
MathUtil.equals(getTabLength(), 0)){
@ -1316,7 +1219,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
return generateTabPointsWithRoot(rootPoints);
}
// 这是一个用于生成标签几何坐标的私有方法。
private Coordinate[] generateTabPointsWithRoot(List<Coordinate> rootPoints) {
final double xTabFront = getTabFrontEdge();
final double xTabTrail = getTabTrailingEdge();
@ -1344,14 +1246,12 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
return combineCurves(tabPoints, rootPoints.toArray(new Coordinate[0]));
}
// 这是一个实现了 Fin 接口的方法,用于获取鳍状物相对于机身的旋转角度偏移量。
@Override
public double getAngleOffset() {
return firstFinOffsetRadians;
}
// 这是一个实现了 Fin 接口的方法,用于设置鳍状物相对于机身的旋转角度偏移量。
@Override
public void setAngleOffset(final double angleRadians) {
for (RocketComponent listener : configListeners) {
@ -1374,13 +1274,11 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
// 这是一个实现了 Fin 接口的方法,用于获取每个鳍状物实例之间的旋转角度增量。
@Override
public double getInstanceAngleIncrement(){
return ( 2*Math.PI / getFinCount());
}
// 这是一个实现了 Fin 接口的方法,用于获取每个鳍状物实例的旋转角度。
@Override
public double[] getInstanceAngles() {
final double angleIncrementRadians = getInstanceAngleIncrement();
@ -1392,14 +1290,12 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
return result;
}
// 这是一个实现了 Fin 接口的方法,用于获取角度计算方法。
@Override
public AngleMethod getAngleMethod() {
return this.angleMethod;
}
// 这是一个实现了 Fin 接口的方法,用于设置角度计算方法。
@Override
public void setAngleMethod(AngleMethod newAngleMethod ) {
for (RocketComponent listener : configListeners) {
@ -1413,7 +1309,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
// 这是一个实现了 Fin 接口的方法,用于获取半径计算方法。
@Override
public RadiusMethod getRadiusMethod() {
return this.radiusMethod;
@ -1435,7 +1330,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
}
// 该方法的作用是设置襟翼组件的实例数量,并通知与 FinSet 相关的监听器进行更新。
@Override
public void setInstanceCount(int newCount) {
for (RocketComponent listener : configListeners) {
@ -1447,13 +1341,11 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
setFinCount(newCount);
}
// 该方法的作用是获取襟翼组件的实例数量,并返回结果。
@Override
public int getInstanceCount() {
return getFinCount();
}
// 该方法的作用是获取襟翼组件的模式名称,并返回结果。
@Override
public String getPatternName() {
return (this.getInstanceCount() + "-fin-ring");
@ -1464,12 +1356,9 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
* Get the span of a single fin. That is, the length from the root to the tip of the fin.
* @return Span of a single fin.
*/
// 该方法的作用是获取单个襟翼的跨度,即从根部到翼尖的长度。由于该方法是抽象方法,其具体实现需要在子类中进行。
// 在 FinSet 的子类中实现该方法时,应该返回单个襟翼的跨度值,单位可以是米、英寸等长度单位。
public abstract double getSpan();
// 该方法用于从指定的 RocketComponent 对象 c 复制属性值到当前 FinSet 对象中,并返回复制后的 RocketComponent 列表。
@Override
protected List<RocketComponent> copyFrom(RocketComponent c) {
FinSet src = (FinSet) c;
@ -1491,13 +1380,10 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
/*
* Handle fin fillet mass properties
*/
// 该方法的作用是获取襟翼圆角部分的材料对象。返回值类型为 Material。
// 在该方法中,直接返回了一个名为 filletMaterial 的属性,该属性应该是一个 Material 对象,用于描述襟翼圆角部分的材料信息。
public Material getFilletMaterial() {
return filletMaterial;
}
// 该方法用于设置襟翼圆角部分的材料对象。参数 mat 是一个 Material 对象,表示要设置的襟翼圆角部分的材料。
public void setFilletMaterial(Material mat) {
for (RocketComponent listener : configListeners) {
if (listener instanceof FinSet) {
@ -1516,13 +1402,11 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
clearPreset();
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
}
// 该方法用于获取襟翼圆角的半径值。
public double getFilletRadius() {
return filletRadius;
}
// 该方法用于设置襟翼圆角的半径值。参数 r 是一个 double 类型的数值,表示要设置的襟翼圆角的半径。
public void setFilletRadius(double r) {
for (RocketComponent listener : configListeners) {
if (listener instanceof FinSet) {
@ -1538,17 +1422,11 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
}
// for debugging. You can safely delete this method
// 该方法用于调试,返回一个字符串,表示给定坐标点数组的描述信息。参数 points 是一个 Coordinate 类型的数组,表示要获取描述
// 信息的坐标点集合;参数 name 是一个 String 类型的字符串,表示要获取描述信息的名称;参数 indent 是一个 String 类型的字
// 符串,表示缩进量。
public static String getPointDescr( final Coordinate[] points, final String name, final String indent){
return getPointDescr(Arrays.asList(points), name, indent);
}
// for debugging. You can safely delete this method
// 该方法用于调试,返回一个字符串,表示给定坐标点列表的描述信息。参数 points 是一个 List<Coordinate> 类型的对象,表示要
// 获取描述信息的坐标点集合;参数 name 是一个 String 类型的字符串,表示要获取描述信息的名称;参数 indent 是一个 String
// 类型的字符串,表示缩进量。
public static String getPointDescr( final List<Coordinate> points, final String name, final String indent){
StringBuilder buf = new StringBuilder();
@ -1561,7 +1439,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
return buf.toString();
}
// 该方法用于生成包含各种坐标点列表描述信息的 StringBuilder 对象,用于调试和输出详细信息。
@Override
public StringBuilder toDebugDetail(){
StringBuilder buf = super.toDebugDetail();
@ -1580,7 +1457,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
return buf;
}
// 这个方法用于计算 FinSet 组件的质心涉及到鳍片、tab 和圆角的体积、质量和质心的计算,并根据鳍片数量的不同进行相应的处理。
private void calculateCM(){
final Coordinate wettedCentroid = calculateSinglePlanformCentroid();
this.singlePlanformArea = wettedCentroid.weight;
@ -1615,10 +1491,6 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
}
// ============= Instanceable Interface Methods ===============
// 实例化接口方法
// 这个方法用于计算 FinSet 组件中每个实例的偏移坐标,涉及到主体半径、实例角度和变换操作的计算,并返回一个包含所有实例偏移
// 坐标的数组。
@Override
public Coordinate[] getInstanceOffsets(){
checkState();
@ -1643,13 +1515,11 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
return toReturn;
}
// 这方法用于获取 FinSet 组件内部颜色组件处理器。
@Override
public InsideColorComponentHandler getInsideColorComponentHandler() {
return this.insideColorComponentHandler;
}
// 这个方法用于设置 FinSet 组件的内部颜色组件处理器
@Override
public void setInsideColorComponentHandler(InsideColorComponentHandler handler) {
this.insideColorComponentHandler = handler;

@ -6,24 +6,22 @@ import net.sf.openrocket.preset.ComponentPreset.Type;
import net.sf.openrocket.startup.Application;
/**
* isFlippedtail cone
* Rocket nose cones of various types. Implemented as a transition with the
* fore radius == 0.
* <p>
* The normal nose cone can be converted to a tail cone by setting the {@link #isFlipped} parameter.
* This will flip all the aft side dimensions with the fore side dimensions.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public class NoseCone extends Transition implements InsideColorComponent {
// 进行国际化和本地化文本翻译
private static final Translator trans = Application.getTranslator();
// 处理内部颜色组件操作
private InsideColorComponentHandler insideColorComponentHandler = new InsideColorComponentHandler(this);
// 鼻锥是否被翻转为true意味着鼻锥被转换为尾锥
private boolean isFlipped;
/********* 构造器 **********/
private boolean isFlipped; // If true, the nose cone is converted to a tail cone
/********* Constructors **********/
public NoseCone() {
this(Transition.Shape.OGIVE, 6 * DEFAULT_RADIUS, DEFAULT_RADIUS);
}
@ -40,34 +38,31 @@ public class NoseCone extends Transition implements InsideColorComponent {
super.setAftRadiusAutomatic(false);
super.setAftRadius(radius);
super.displayOrder_side = 1; // 在二维侧视图中显示组件的顺序
super.displayOrder_back = 0; // 在二维背视图中显示组件的顺序
super.displayOrder_side = 1; // Order for displaying the component in the 2D side view
super.displayOrder_back = 0; // Order for displaying the component in the 2D back view
}
/********** 头锥体尺寸 **********/
/********** Nose cone dimensions **********/
/**
*
* @return
* Returns the base radius of the nose cone (independent of whether the nose cone is flipped or not).
* This method should be used over {@link #getAftRadius()} because it works for both normal and flipped nose cones.
*/
public double getBaseRadius() {
return isFlipped ? getForeRadius() : getAftRadius();
}
/**
*
* @return
* Returns the raw base radius of the nose cone (independent of whether the nose cone is flipped or not).
* This method should be used over {@link #getAftRadiusNoAutomatic()} because it works for both normal and flipped nose cones.
*/
public double getBaseRadiusNoAutomatic() {
return isFlipped ? getForeRadiusNoAutomatic() : getAftRadiusNoAutomatic();
}
/**
*
* @param radius
* Sets the base radius of the nose cone (independent of whether the nose cone is flipped or not).
* This method should be used over {@link #setAftRadius(double)} because it works for both normal and flipped nose cones.
*/
public void setBaseRadius(double radius) {
if (isFlipped) {
@ -77,19 +72,19 @@ public class NoseCone extends Transition implements InsideColorComponent {
}
}
/**
*
* @return boolean
* Returns whether the base radius of the nose cone takes it settings from the previous/next component
* (independent of whether the nose cone is flipped or not).
* This method should be used over {@link #isAftRadiusAutomatic()} because it works for both normal and flipped nose cones.
*/
public boolean isBaseRadiusAutomatic() {
return isFlipped ? isForeRadiusAutomatic() : isAftRadiusAutomatic();
}
/**
*
* @param auto
* Sets whether the base radius of the nose cone takes it settings from the previous/next component
* (independent of whether the nose cone is flipped or not).
* This method should be used over {@link #setAftRadiusAutomatic(boolean)} because it works for both normal and flipped nose cones.
*/
public void setBaseRadiusAutomatic(boolean auto) {
if (isFlipped) {
@ -100,19 +95,17 @@ public class NoseCone extends Transition implements InsideColorComponent {
}
/**
*
* @return double
* Returns the shoulder length, regardless of how the nose cone is flipped (independent of whether the nose cone is flipped or not).
* This method should be used over {@link #getAftShoulderLength()} because it works for both normal and flipped nose cones.
*/
public double getShoulderLength() {
return isFlipped ? getForeShoulderLength() : getAftShoulderLength();
}
/**
*
* @param length
* Sets the shoulder length (independent of whether the nose cone is flipped or not).
* This method should be used over {@link #setAftShoulderLength(double)} because it works for both normal and flipped nose cones.
*/
public void setShoulderLength(double length) {
if (isFlipped) {
@ -122,19 +115,17 @@ public class NoseCone extends Transition implements InsideColorComponent {
}
}
/**
*
* @return double
* Returns the shoulder radius (independent of whether the nose cone is flipped or not).
* This method should be used over {@link #getAftShoulderRadius()} because it works for both normal and flipped nose cones.
*/
public double getShoulderRadius() {
return isFlipped ? getForeShoulderRadius() : getAftShoulderRadius();
}
/**
*
* @param radius
* Sets the shoulder radius (independent of whether the nose cone is flipped or not).
* This method should be used over {@link #setAftShoulderRadius(double)} because it works for both normal and flipped nose cones.
*/
public void setShoulderRadius(double radius) {
if (isFlipped) {
@ -144,19 +135,17 @@ public class NoseCone extends Transition implements InsideColorComponent {
}
}
/**
*
* @return double
* Returns the shoulder thickness (independent of whether the nose cone is flipped or not).
* This method should be used over {@link #getAftShoulderThickness()} because it works for both normal and flipped nose cones.
*/
public double getShoulderThickness() {
return isFlipped ? getForeShoulderThickness() : getAftShoulderThickness();
}
/**
*
* @param thickness
* Sets the shoulder thickness (independent of whether the nose cone is flipped or not).
* This method should be used over {@link #setAftShoulderRadius(double)} because it works for both normal and flipped nose cones.
*/
public void setShoulderThickness(double thickness) {
if (isFlipped) {
@ -166,19 +155,17 @@ public class NoseCone extends Transition implements InsideColorComponent {
}
}
/**
*
* @return boolean
* Returns the shoulder cap (independent of whether the nose cone is flipped or not).
* This method should be used over {@link #isAftShoulderCapped()} because it works for both normal and flipped nose cones.
*/
public boolean isShoulderCapped() {
return isFlipped ? isForeShoulderCapped() : isAftShoulderCapped();
}
/**
*
* @param capped
* Sets the shoulder cap (independent of whether the nose cone is flipped or not).
* This method should be used over {@link #setAftShoulderCapped(boolean)} because it works for both normal and flipped nose cones.
*/
public void setShoulderCapped(boolean capped) {
if (isFlipped) {
@ -190,20 +177,17 @@ public class NoseCone extends Transition implements InsideColorComponent {
/********** Other **********/
/**
* flipped
* @return boolean
* Return true if the nose cone is flipped, i.e. converted to a tail cone, false if it is a regular nose cone.
*/
public boolean isFlipped() {
return isFlipped;
}
/**
* flipped,
* @param flipped
* @param sanityCheck
* Set the nose cone to be flipped, i.e. converted to a tail cone, or set it to be a regular nose cone.
* @param flipped if true, the nose cone is converted to a tail cone, if false it is a regular nose cone.
* @param sanityCheck whether to check if the auto radius parameter can be used for the new nose cone orientation
*/
public void setFlipped(boolean flipped, boolean sanityCheck) {
for (RocketComponent listener : configListeners) {
@ -243,19 +227,14 @@ public class NoseCone extends Transition implements InsideColorComponent {
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
/**
* flipped
* @param flipped
* Set the nose cone to be flipped, i.e. converted to a tail cone, or set it to be a regular nose cone.
* @param flipped if true, the nose cone is converted to a tail cone, if false it is a regular nose cone.
*/
public void setFlipped(boolean flipped) {
setFlipped(flipped, true);
}
/**
*
*/
private void resetForeRadius() {
setForeRadius(0);
setForeRadiusAutomatic(false);
@ -265,9 +244,6 @@ public class NoseCone extends Transition implements InsideColorComponent {
setForeShoulderCapped(false);
}
/**
*
*/
private void resetAftRadius() {
setAftRadius(0);
setAftRadiusAutomatic(false);
@ -277,43 +253,23 @@ public class NoseCone extends Transition implements InsideColorComponent {
setAftShoulderCapped(false);
}
/**
*
* @return boolean
*/
@Override
public boolean isClipped() {
return false;
}
/**
*
* @param b
*/
@Override
public void setClipped(boolean b) {
// No-op
}
/********** 火箭组件方法 **********/
/**
*
* @return
*/
/********** RocketComponent methods **********/
@Override
public Type getPresetType() {
return ComponentPreset.Type.NOSE_CONE;
}
/**
* preset
* @param preset
*/
@Override
protected void loadFromPreset(ComponentPreset preset) {
// We first need to unflip, because the preset loading always applies settings for a normal nose cone (e.g. aft diameter)
@ -324,10 +280,8 @@ public class NoseCone extends Transition implements InsideColorComponent {
setFlipped(flipped);
}
/**
*
* @return
* Return component name.
*/
@Override
public String getComponentName() {
@ -336,20 +290,11 @@ public class NoseCone extends Transition implements InsideColorComponent {
}
/**
*
* @return
*/
@Override
public InsideColorComponentHandler getInsideColorComponentHandler() {
return this.insideColorComponentHandler;
}
/**
*
* @param handler
*/
@Override
public void setInsideColorComponentHandler(InsideColorComponentHandler handler) {
this.insideColorComponentHandler = handler;

@ -20,21 +20,13 @@ import net.sf.openrocket.util.MathUtil;
*/
public abstract class RecoveryDevice extends MassObject implements FlightConfigurableComponent {
////
// 表示拖力系数Drag Coefficient用于描述降落装置在空气中运动时所受到的阻力大小。
protected double DragCoefficient;
// 表示降落伞的拖力系数Drag Coefficient
protected double cd = Parachute.DEFAULT_CD;
// 表示是否自动计算降落伞的拖力系数。如果设置为true则会根据降落伞的形状和尺寸等参数自动计算拖力系数如果设置为false
// 则需要手动指定拖力系数。
protected boolean cdAutomatic = true;
////
// 表示默认的材料表面Material Surface。这是一个Material.Surface类型的对象用于存储材料的表面属性如摩擦系数、表面
// 粗糙度等。
private final Material.Surface defaultMaterial;
// 表示降落装置的材料表面Material Surface。这是一个Material.Surface类型的对象用于存储降落装置的材料表面属性。
private Material.Surface material;
// 表示部署配置参数集合Deployment Configuration。这是一个FlightConfigurableParameterSet<DeploymentConfiguration>
// 类型的对象,用于存储多个部署配置参数。
private FlightConfigurableParameterSet<DeploymentConfiguration> deploymentConfigurations;
public RecoveryDevice() {
@ -73,12 +65,11 @@ public abstract class RecoveryDevice extends MassObject implements FlightConfigu
fireComponentChangeEvent(ComponentChangeEvent.AERODYNAMIC_CHANGE);
}
// 它的作用是返回当前的回收装置Recovery Device是否自动计算阻力系数Drag Coefficient
public boolean isCDAutomatic() {
return cdAutomatic;
}
// 它的作用是设置回收装置Recovery Device是否自动计算阻力系数Drag Coefficient
public void setCDAutomatic(boolean auto) {
for (RocketComponent listener : configListeners) {
if (listener instanceof RecoveryDevice) {
@ -115,30 +106,25 @@ public abstract class RecoveryDevice extends MassObject implements FlightConfigu
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
}
// 它的作用是获取回收装置Recovery Device的部署配置Deployment Configuration集合。
public FlightConfigurableParameterSet<DeploymentConfiguration> getDeploymentConfigurations() {
return deploymentConfigurations;
}
// 它的作用是复制回收装置Recovery Device的飞行配置Flight Configuration
@Override
public void copyFlightConfiguration(FlightConfigurationId oldConfigId, FlightConfigurationId newConfigId) {
deploymentConfigurations.copyFlightConfiguration(oldConfigId, newConfigId);
}
// 它的作用是重置回收装置Recovery Device的飞行配置Flight Configuration
@Override
public void reset( final FlightConfigurationId fcid){
deploymentConfigurations.reset(fcid);
}
// 它的作用是计算回收装置Recovery Device的质量mass
@Override
public double getComponentMass() {
return getArea() * getMaterial().getDensity();
}
// 它的作用是从预设preset中加载回收装置Recovery Device的配置。
@Override
protected void loadFromPreset(ComponentPreset preset) {
// // Set preset parachute line material
@ -159,7 +145,6 @@ public abstract class RecoveryDevice extends MassObject implements FlightConfigu
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
// 它的作用是复制回收装置Recovery Device对象并将其原始IDoriginal ID保留。
@Override
protected RocketComponent copyWithOriginalID() {
RecoveryDevice copy = (RecoveryDevice) super.copyWithOriginalID();
@ -167,7 +152,6 @@ public abstract class RecoveryDevice extends MassObject implements FlightConfigu
return copy;
}
// 它的作用是向回收装置Recovery Device添加配置监听器config listener
@Override
public boolean addConfigListener(RocketComponent listener) {
boolean success = super.addConfigListener(listener);
@ -180,7 +164,6 @@ public abstract class RecoveryDevice extends MassObject implements FlightConfigu
return false;
}
// 它的作用是移除回收装置Recovery Device对象的配置监听器config listener
@Override
public void removeConfigListener(RocketComponent listener) {
super.removeConfigListener(listener);
@ -191,7 +174,6 @@ public abstract class RecoveryDevice extends MassObject implements FlightConfigu
}
}
// 它的作用是清除回收装置Recovery Device对象的配置监听器config listener
@Override
public void clearConfigListeners() {
super.clearConfigListeners();

@ -1,26 +1,26 @@
package net.sf.openrocket.rocketcomponent;
import java.util.Collection;
import net.sf.openrocket.util.Coordinate;
public abstract class RocketUtils {
public static double getLength(Rocket rocket) {
double length = 0;
Collection<Coordinate> bounds = rocket.getSelectedConfiguration().getBounds();
if (!bounds.isEmpty()) {
double minX = Double.POSITIVE_INFINITY, maxX = Double.NEGATIVE_INFINITY;
for (Coordinate c : bounds) {
if (c.x < minX)
minX = c.x;
if (c.x > maxX)
maxX = c.x;
}
length = maxX - minX;
}
return length;
}
}
package net.sf.openrocket.rocketcomponent;
import java.util.Collection;
import net.sf.openrocket.util.Coordinate;
public abstract class RocketUtils {
public static double getLength(Rocket rocket) {
double length = 0;
Collection<Coordinate> bounds = rocket.getSelectedConfiguration().getBounds();
if (!bounds.isEmpty()) {
double minX = Double.POSITIVE_INFINITY, maxX = Double.NEGATIVE_INFINITY;
for (Coordinate c : bounds) {
if (c.x < minX)
minX = c.x;
if (c.x > maxX)
maxX = c.x;
}
length = maxX - minX;
}
return length;
}
}

@ -60,7 +60,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
}
//////// Length ////////
// 方法的作用是设置过渡部分的长度,并在长度改变时执行一些额外的操作,包括清除预设值或状态。
@Override
public void setLength( double length ) {
if ( this.length == length ) {
@ -75,7 +74,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
//////// Fore radius ////////
// 方法的作用是获取过渡部分的前半径。根据情况,它可能返回自动计算的前半径值或者直接返回手动设置的前半径值。
@Override
public double getForeRadius() {
if (isForeRadiusAutomatic()) {
@ -88,7 +86,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
* Returns the automatic radius from the front, taken from the previous component. Returns the default radius if there
* is no previous component.
*/
// 方法的作用是获取从前端自动计算的半径值,该值来自于前一个组件的半径。如果没有前一个组件,则返回默认的半径值。
protected double getAutoForeRadius() {
SymmetricComponent c = this.getPreviousSymmetricComponent();
if (c != null) {
@ -102,7 +99,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
* Return the fore radius that was manually entered, so not the value that the component received from automatic
* fore radius.
*/
// 方法的作用是返回手动输入的前半径值,而不是自动计算得到的前半径值。
public double getForeRadiusNoAutomatic() {
return foreRadius;
}
@ -112,8 +108,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
* @param radius new radius
* @param doClamping whether to clamp the thickness
*/
// 方法的作用是设置前半径的新值,并提供一个选项来夹紧厚度以适应新的半径值。同时,它还更新自动计算标志、清除预设值并触发
// 组件更改事件。
public void setForeRadius(double radius, boolean doClamping) {
for (RocketComponent listener : configListeners) {
if (listener instanceof Transition) {
@ -134,12 +128,10 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
// 方法的作用是设置前半径的新值,并默认夹紧厚度以适应新的半径值。
public void setForeRadius(double radius) {
setForeRadius(radius, true);
}
// 方法的作用是返回前半径是否自动计算的标志。
@Override
public boolean isForeRadiusAutomatic() {
return autoForeRadius;
@ -151,7 +143,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
* @param auto whether to set the fore radius to automatic mode
* @param sanityCheck whether to sanity check auto mode for whether there is a previous component of which you can take the radius
*/
// 方法的作用是设置前半径是否自动计算的标志,并触发相应的事件通知。
public void setForeRadiusAutomatic(boolean auto, boolean sanityCheck) {
for (RocketComponent listener : configListeners) {
if (listener instanceof Transition) {
@ -173,7 +164,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
// 方法的作用是设置前半径是否自动计算的标志,并调用另一个重载方法来完成设置。
public void setForeRadiusAutomatic(boolean auto) {
setForeRadiusAutomatic(auto, false);
}
@ -181,7 +171,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
//////// Aft radius /////////
// 方法的作用是获取过渡段的后半径。
@Override
public double getAftRadius() {
if (isAftRadiusAutomatic()) {
@ -194,7 +183,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
* Returns the automatic radius from the rear, taken from the next component. Returns the default radius if there
* is no next component.
*/
// 方法的作用是获取从后方自动计算的半径值,该值来自下一个对称组件,如果没有下一个对称组件,则返回默认半径值。
protected double getAutoAftRadius() {
SymmetricComponent c = this.getNextSymmetricComponent();
if (c != null) {
@ -208,7 +196,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
* Return the aft radius that was manually entered, so not the value that the component received from automatic
* zft radius.
*/
// 方法的作用是获取手动输入的后半径值,而不是从自动计算的后半径值中获取的值。
public double getAftRadiusNoAutomatic() {
return aftRadius;
}
@ -218,7 +205,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
* @param radius new radius
* @param doClamping whether to clamp the thickness
*/
// 方法的作用是设置新的后半径值,并提供是否将厚度限制在新半径内的选项。
public void setAftRadius(double radius, boolean doClamping) {
for (RocketComponent listener : configListeners) {
if (listener instanceof Transition) {
@ -239,13 +225,10 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
// 方法的作用是设置新的后半径值,并将厚度限制在新半径内(即调用 setAftRadius(radius, true) 方法)。它是对
// setAftRadius(double radius, boolean doClamping) 方法的简单封装,方便在不需要自定义限制行为时使用。
public void setAftRadius(double radius) {
setAftRadius(radius, true);
}
// 方法的作用是返回后半径是否是自动计算的。
@Override
public boolean isAftRadiusAutomatic() {
return autoAftRadius;
@ -257,7 +240,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
* @param auto whether to set the aft radius to automatic mode
* @param sanityCheck whether to sanity check auto mode for whether there is a next component of which you can take the radius
*/
// 方法的作用是设置后半径是否为自动模式,并提供是否进行合理性检查的选项。
public void setAftRadiusAutomatic(boolean auto, boolean sanityCheck) {
for (RocketComponent listener : configListeners) {
if (listener instanceof Transition) {
@ -279,7 +261,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
// 方法的作用是设置后半径是否为自动模式,并且不进行合理性检查。
public void setAftRadiusAutomatic(boolean auto) {
setAftRadiusAutomatic(auto, false);
}
@ -287,7 +268,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
//// Radius automatics
// 方法的作用是获取前半径的自动计算值。如果后半径是自动计算的,则返回 -1否则返回后半径的值作为前半径的自动计算值。
@Override
protected double getFrontAutoRadius() {
if (isAftRadiusAutomatic())
@ -296,7 +276,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
}
// 方法的作用是获取后半径的自动计算值。如果前半径是自动计算的,则返回 -1否则返回前半径的值作为后半径的自动计算值。
@Override
protected double getRearAutoRadius() {
if (isForeRadiusAutomatic())
@ -304,13 +283,11 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
return getForeRadius();
}
// 方法的作用是判断当前组件是否使用前一组件的自动计算值。如果前半径是自动计算的,则返回 true否则返回 false。
@Override
public boolean usesPreviousCompAutomatic() {
return isForeRadiusAutomatic();
}
// 方法的作用是判断当前组件是否使用后一组件的自动计算值。如果后半径是自动计算的,则返回 true否则返回 false。
@Override
public boolean usesNextCompAutomatic() {
return isAftRadiusAutomatic();
@ -321,8 +298,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
* @return false if there is no previous symmetric component, or if the previous component already has this component
* as its auto dimension reference
*/
// 方法的作用是检查当前组件是否可以使用前一个对称组件的自动计算半径。如果前一个对称组件不存在或已经将当前组件作为其自动
// 计算半径的参考,则返回 false否则返回 true。
public boolean canUsePreviousCompAutomatic() {
SymmetricComponent referenceComp = getPreviousSymmetricComponent();
if (referenceComp == null) {
@ -336,8 +311,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
* @return false if there is no next symmetric component, or if the next component already has this component
* as its auto dimension reference
*/
// 方法的作用是检查当前组件是否可以使用后一个对称组件的自动计算半径。如果后一个对称组件不存在或已经将当前组件作为其自动
// 计算半径的参考,则返回 false否则返回 true。
public boolean canUseNextCompAutomatic() {
SymmetricComponent referenceComp = getNextSymmetricComponent();
if (referenceComp == null) {
@ -349,12 +322,10 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
//////// Type & shape /////////
// 方法的作用是获取当前组件的类型(即形状)。它通过返回当前组件的 type 成员变量来实现这一功能。
public Shape getType() {
return type;
}
// 方法的作用是设置当前组件的类型(即形状)。它将给定的形状类型应用于当前组件,并触发一系列相关的操作和事件。
public void setType(Shape type) {
for (RocketComponent listener : configListeners) {
if (listener instanceof Transition) {
@ -378,12 +349,10 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
// getShapeParameter() 方法的作用是获取当前组件的形状参数。它通过返回当前组件的 shapeParameter 成员变量来实现这一功能。
public double getShapeParameter() {
return shapeParameter;
}
// 方法的作用是设置当前组件的形状参数。它将给定的形状参数应用于当前组件,并触发一系列相关的操作和事件。
public void setShapeParameter(double n) {
for (RocketComponent listener : configListeners) {
if (listener instanceof Transition) {
@ -401,14 +370,12 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
// 方法的作用是判断当前组件是否被截断。它首先检查当前组件类型是否支持被截断,如果支持,则返回当前组件的 clipped 属性值。
public boolean isClipped() {
if (!type.isClippable())
return false;
return clipped;
}
// 方法的作用是设置当前组件是否被截断。它将给定的截断状态应用于当前组件,并触发一系列相关的操作和事件。
public void setClipped(boolean c) {
for (RocketComponent listener : configListeners) {
if (listener instanceof Transition) {
@ -422,18 +389,14 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
// 方法的作用是检查当前组件类型是否支持被截断。它通过调用当前组件类型的 isClippable() 方法来实现这个功能,并将结果返回给
// 调用者。
public boolean isClippedEnabled() {
return type.isClippable();
}
// 方法的作用是获取当前组件类型的形状参数的最小值。
public double getShapeParameterMin() {
return type.minParameter();
}
// 方法的作用是获取当前组件类型的形状参数的最大值。
public double getShapeParameterMax() {
return type.maxParameter();
}
@ -441,12 +404,10 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
//////// Shoulders ////////
// 方法的作用是获取肩部的前半径。
public double getForeShoulderRadius() {
return foreShoulderRadius;
}
// 方法的作用是设置肩部的前半径。
public void setForeShoulderRadius(double foreShoulderRadius) {
for (RocketComponent listener : configListeners) {
if (listener instanceof Transition) {
@ -461,12 +422,10 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
}
// 方法的作用是获取肩部的前厚度。
public double getForeShoulderThickness() {
return foreShoulderThickness;
}
// 方法的作用是设置肩部的前厚度。
public void setForeShoulderThickness(double foreShoulderThickness) {
for (RocketComponent listener : configListeners) {
if (listener instanceof Transition) {
@ -480,12 +439,10 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
}
// 方法的作用是获取肩部的前长度。
public double getForeShoulderLength() {
return foreShoulderLength;
}
// 方法的作用是设置肩部的前长度。
public void setForeShoulderLength(double foreShoulderLength) {
for (RocketComponent listener : configListeners) {
if (listener instanceof Transition) {
@ -499,12 +456,10 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
}
// 方法的作用是判断肩部是否有前盖。
public boolean isForeShoulderCapped() {
return foreShoulderCapped;
}
// 方法的作用是设置肩部是否有前盖。
public void setForeShoulderCapped(boolean capped) {
for (RocketComponent listener : configListeners) {
if (listener instanceof Transition) {
@ -520,12 +475,11 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
// 方法的作用是获取肩部的后半径。
public double getAftShoulderRadius() {
return aftShoulderRadius;
}
// 方法的作用是设置肩部的后半径。
public void setAftShoulderRadius(double aftShoulderRadius) {
for (RocketComponent listener : configListeners) {
if (listener instanceof Transition) {
@ -540,12 +494,10 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
}
// 方法的作用是获取肩部的后厚度。
public double getAftShoulderThickness() {
return aftShoulderThickness;
}
// 方法的作用是设置肩部的后厚度。
public void setAftShoulderThickness(double aftShoulderThickness) {
for (RocketComponent listener : configListeners) {
if (listener instanceof Transition) {
@ -559,12 +511,10 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
}
// 方法的作用是获取肩部的后长度。
public double getAftShoulderLength() {
return aftShoulderLength;
}
// 方法的作用是设置肩部的后长度。
public void setAftShoulderLength(double aftShoulderLength) {
for (RocketComponent listener : configListeners) {
if (listener instanceof Transition) {
@ -578,12 +528,10 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
}
// 方法的作用是获取肩部的后端是否有盖子。
public boolean isAftShoulderCapped() {
return aftShoulderCapped;
}
// 方法的作用是设置肩部的后端是否有盖子。
public void setAftShoulderCapped(boolean capped) {
for (RocketComponent listener : configListeners) {
if (listener instanceof Transition) {
@ -607,7 +555,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
/**
* Return the radius at point x of the transition.
*/
// 方法的作用是计算过渡形状在某一位置上的半径。
@Override
public double getRadius(double x) {
if ( x < 0 )
@ -644,7 +591,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
* r1 == type.getRadius(clipLength,r2,clipLength+length)
* using a binary search. It assumes getOuterRadius() to be monotonically increasing.
*/
// 这是一个用于数值求解的方法,目的是解方程
private void calculateClip(double r1, double r2) {
double min = 0, max = length;
@ -690,14 +636,14 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
}
}
// 方法用于计算过渡形状在某一位置 x 上的内半径。
@Override
public double getInnerRadius(double x) {
return Math.max(getRadius(x) - thickness, 0);
}
// 该方法用于获取组件的边界坐标集合。
@Override
public Collection<Coordinate> getComponentBounds() {
Collection<Coordinate> bounds = super.getComponentBounds();
@ -708,7 +654,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
return bounds;
}
// 该方法用于计算组件的体积。
@Override
public double getComponentVolume() {
double volume = super.getComponentVolume();
@ -735,8 +680,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
return volume;
}
// 该方法用于计算组件的重心坐标。
@Override
public Coordinate getComponentCG() {
Coordinate cg = super.getComponentCG();
@ -772,22 +715,18 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
* However, since the mass is corrected, the inertia is automatically corrected
* to very nearly the correct value.
*/
// 对于肩部区域惯性矩moments of inertia没有进行明确的修正。然而由于质量已经进行了修正惯性矩也会自动地接近
// 正确的值。
/**
* Returns the name of the component ("Transition").
*/
// 该方法用于返回过渡件Transition组件的名称。
@Override
public String getComponentName() {
//// Transition
return trans.get("Transition.Transition");
}
// 该方法的作用是在组件发生改变时执行必要的处理操作其中包括调用父类的处理逻辑和重置clipLength变量。
@Override
protected void componentChanged(ComponentChangeEvent e) {
super.componentChanged(e);
@ -801,8 +740,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
* @param comptype The RocketComponent class type to add.
* @return Whether such a component can be added.
*/
// 它的作用是检查给定类型的组件是否可以添加到该过渡件Transition组件中。
@Override
public boolean isCompatible(Class<? extends RocketComponent> comptype) {
if (InternalComponent.class.isAssignableFrom(comptype)){
@ -813,14 +750,12 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
return false;
}
// 它的作用是返回该过渡件Transition组件的预设类型。
@Override
public Type getPresetType() {
return ComponentPreset.Type.TRANSITION;
}
// 它的作用是从预设preset中加载过渡件Transition组件的属性。
@Override
protected void loadFromPreset(ComponentPreset preset) {
@ -874,13 +809,11 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
}
// 它的作用是返回一个InsideColorComponentHandler类型的对象。
@Override
public InsideColorComponentHandler getInsideColorComponentHandler() {
return this.insideColorComponentHandler;
}
// 它的作用是设置内部颜色组件处理器InsideColorComponentHandler
@Override
public void setInsideColorComponentHandler(InsideColorComponentHandler handler) {
this.insideColorComponentHandler = handler;
@ -897,7 +830,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
* Conical shape.
*/
//// Conical
// 这段代码的作用是定义了一个锥形过渡件的特性和计算半径的方法。
CONICAL(trans.get("Shape.Conical"),
//// A conical nose cone has a profile of a triangle.
trans.get("Shape.Conical.desc1"),
@ -918,7 +850,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
* for smaller values the shape straightens out into a cone at param==0.
*/
//// Ogive
// OGIVE代表拱形过渡件ogive transition它描述了一个拱形的过渡部分通常用于连接不同直径的部件。
OGIVE(trans.get("Shape.Ogive"),
//// An ogive nose cone has a profile that is a segment of a circle. The shape parameter value 1 produces a <b>tangent ogive</b>, which has a smooth transition to the body tube, values less than 1 produce <b>secant ogives</b>.
trans.get("Shape.Ogive.desc1"),
@ -966,7 +897,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
* Ellipsoidal shape.
*/
//// Ellipsoid
// ELLIPSOID代表椭球形过渡件ellipsoidal transition它描述了一个椭球形的过渡部分通常用于连接不同直径的部件。
ELLIPSOID(trans.get("Shape.Ellipsoid"),
//// An ellipsoidal nose cone has a profile of a half-ellipse with major axes of lengths 2&times;<i>Length</i> and <i>Diameter</i>.
trans.get("Shape.Ellipsoid.desc1"),
@ -983,7 +913,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
},
//// Power series
// POWER代表幂级数形状power series它描述了一种随着距离变化而变化的半径曲线。
POWER(trans.get("Shape.Powerseries"),
trans.get("Shape.Powerseries.desc1"),
trans.get("Shape.Powerseries.desc2"), true) {
@ -1016,7 +945,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
},
//// Parabolic series
// PARABOLIC代表抛物线形状parabolic series它描述了一种随着距离变化而变化的半径曲线。
PARABOLIC(trans.get("Shape.Parabolicseries"),
////A parabolic series nose cone has a profile of a parabola. The shape parameter defines the segment of the parabola to utilize. The shape parameter 1.0 produces a <b>full parabola</b> which is tangent to the body tube, 0.75 produces a <b>3/4 parabola</b>, 0.5 procudes a <b>1/2 parabola</b> and 0 produces a <b>conical</b> nose cone.
trans.get("Shape.Parabolicseries.desc1"),
@ -1049,7 +977,6 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
},
//// Haack series
// HAACK代表Haack系列形状Haack series它描述了一种随着距离变化而变化的半径曲线。
HAACK(trans.get("Shape.Haackseries"),
//// The Haack series nose cones are designed to minimize drag. The shape parameter 0 produces an <b>LD-Haack</b> or <b>Von Karman</b> nose cone, which minimizes drag for fixed length and diameter, while a value of 0.333 produces an <b>LV-Haack</b> nose cone, which minimizes drag for fixed length and volume.
trans.get("Shape.Haackseries.desc1"),

@ -59,8 +59,7 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
super.displayOrder_side = 3; // Order for displaying the component in the 2D side view
super.displayOrder_back = 3; // Order for displaying the component in the 2D back view
}
// 这个方法用于设置 TubeFinSet 组件的长度,并在长度发生变化时触发相应的事件通知。
public void setLength(double length) {
for (RocketComponent listener : configListeners) {
if (listener instanceof TubeFinSet) {
@ -74,8 +73,7 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
// 这个方法用于判断是否自动计算外半径。
public boolean isOuterRadiusAutomatic() {
return autoRadius;
}
@ -85,7 +83,6 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
*
* @return the outside radius of the tube
*/
// 这个方法用于获取 TubeFinSet 的外半径。
public double getOuterRadius() {
if (autoRadius) {
if (fins < 3) {
@ -102,7 +99,6 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
*
* @return distance between tubes. 0 if touching, negative if overlap
*/
// 这个方法用于获取 TubeFinSet 中管道之间的距离。
public double getTubeSeparation() {
return 2.0*(getTouchingRadius() - getOuterRadius());
}
@ -112,7 +108,6 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
*
* @return required radius
*/
// 这个方法用于计算鳍与主体管道相接触时,所需的半径大小。
private double getTouchingRadius() {
double r = getBodyRadius();
final double finSep = Math.PI / fins;
@ -128,7 +123,6 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
*
* @param radius the outside radius in standard units
*/
// 这个方法用于设置管道鳍的外半径。
public void setOuterRadius(double radius) {
for (RocketComponent listener : configListeners) {
if (listener instanceof TubeFinSet) {
@ -151,7 +145,6 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
/**
* Sets whether the radius is selected automatically or not.
*/
// 这个方法用于设置是否自动选择管道鳍的外半径。
public void setOuterRadiusAutomatic(boolean auto) {
for (RocketComponent listener : configListeners) {
if (listener instanceof TubeFinSet) {
@ -166,13 +159,11 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
clearPreset();
}
// 这个方法用于获取管道鳍的内半径。
public double getInnerRadius() {
return Math.max(getOuterRadius() - thickness, 0);
}
// 这个方法用于设置管道鳍的内半径。
public void setInnerRadius(double r) {
for (RocketComponent listener : configListeners) {
if (listener instanceof TubeFinSet) {
@ -186,7 +177,6 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
/**
* Return the component wall thickness.
*/
// 这个方法用于获取管道鳍的壁厚。
public double getThickness() {
return Math.min(thickness, getOuterRadius());
}
@ -196,7 +186,6 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
* Set the component wall thickness. Values greater than the maximum radius are not
* allowed, and will result in setting the thickness to the maximum radius.
*/
// 这个方法用于设置管道鳍的壁厚。
public void setThickness(double thickness) {
for (RocketComponent listener : configListeners) {
if (listener instanceof TubeFinSet) {
@ -216,13 +205,10 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
* Return the number of fins in the set.
* @return The number of fins.
*/
// 这个方法用于获取管道鳍组件中鳍片的数量。
public int getFinCount() {
return fins;
}
// 这个方法用于判断当前管道鳍组件是否位于火箭的其他组件之后。
// 该方法始终返回 false即表示当前管道鳍组件不位于其他组件之后。
@Override
public boolean isAfter(){
return false;
@ -232,7 +218,6 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
* Sets the number of fins in the set.
* @param n The number of fins, greater of equal to one.
*/
// 这个方法用于设置管道鳍组件中鳍片的数量。
public void setFinCount(int n) {
for (RocketComponent listener : configListeners) {
if (listener instanceof TubeFinSet) {
@ -255,12 +240,10 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
* Gets the base rotation amount of the first fin.
* @return The base rotation amount.
*/
// 这个方法用于获取第一个鳍片的基本旋转角度。
public double getBaseRotation() {
return getAngleOffset();
}
// 这个方法用于获取鳍片的旋转角度。
public double getFinRotation() {
return 2 * Math.PI / fins;
}
@ -269,7 +252,6 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
* Sets the base rotation amount of the first fin.
* @param r The base rotation amount.
*/
// 这个方法用于设置第一个鳍片的基本旋转角度。
public void setBaseRotation(double r) {
for (RocketComponent listener : configListeners) {
if (listener instanceof TubeFinSet) {
@ -279,26 +261,21 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
setAngleOffset(r);
}
// 这个方法用于获取基本旋转角度的变换。
public Transformation getBaseRotationTransformation() {
return baseRotation;
}
// 这个方法用于获取鳍片旋转的变换。
public Transformation getFinRotationTransformation() {
return finRotation;
}
// 这个方法的作用是设置轴向方法,并触发相应的组件事件。通过调用该方法,可以改变火箭模型中使用的轴向方法,并通知其他相关组件
// 进行相应的更新和调整。
@Override
public void setAxialMethod(AxialMethod position) {
super.setAxialMethod(position);
fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE);
}
// 这个方法的作用是计算并返回组件的体积。
@Override
public double getComponentVolume() {
double or = getOuterRadius();
@ -309,16 +286,13 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
volume *= fins;
return volume;
}
// 这个方法的作用是获取组件的名称,并可能根据本地化设置返回对应的翻译文本。通过调用该方法,可以获取火箭模型中特定组件的名称
// 信息。
@Override
public String getComponentName() {
//// Tube Fin Set
return trans.get("TubeFinSet.TubeFinSet");
}
// 这个方法的作用是计算并返回组件的重心坐标。通过调用该方法,可以获取火箭模型中特定组件的重心位置信息。
@Override
public Coordinate getComponentCG() {
double mass = getComponentMass(); // safe
@ -331,8 +305,7 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
}
}
// 这个方法的作用是计算并返回组件在纵向方向上的单位惯性矩。通过调用该方法,可以获取火箭模型中特定组件的惯性相关信息。
@Override
public double getLongitudinalUnitInertia() {
// Longitudinal Unit Inertia for a single tube fin.
@ -349,9 +322,7 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
}
return totalInertia;
}
// 这个方法的作用是计算并返回单个鳍片绕其中心的旋转惯性矩,或者根据平行轴定理计算多个鳍片绕其中心的总旋转惯性矩。通过调用该
// 方法,可以获取火箭模型中特定组件的旋转惯性相关信息。
@Override
public double getRotationalUnitInertia() {
// The rotational inertia of a single fin about its center.
@ -364,30 +335,23 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
return fins * (icentermass + MathUtil.pow2(getOuterRadius()) + getBodyRadius());
}
}
// 这个方法的作用是判断当前组件是否允许包含子组件。通过调用该方法,可以确定是否可以向该组件添加子组件或者进行其他与子组件相关
// 的操作。
@Override
public boolean allowsChildren() {
return false;
}
// 这个方法的作用是获取当前组件的预设类型。通过调用该方法,可以确定该组件的类型,并据此进行一些与组件类型相关的操作,例如设置
// 组件的属性、行为或样式等。
@Override
public Type getPresetType() {
return ComponentPreset.Type.BODY_TUBE;
}
// 这个方法的作用是判断当前组件是否与给定类型的组件兼容。通过调用该方法,可以确定是否可以将该组件与其他类型的组件进行某些操作。
@Override
public boolean isCompatible(Class<? extends RocketComponent> type) {
// TODO Auto-generated method stub
return false;
}
// 这个方法的作用是获取当前组件的边界坐标。通过调用该方法,可以确定该组件在模型中所占据的位置和大小,从而进行一些与位置、
// 对齐或碰撞检测相关的操作。
@Override
public Collection<Coordinate> getComponentBounds() {
List<Coordinate> bounds = new ArrayList<Coordinate>();
@ -398,9 +362,7 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
return bounds;
}
// 这个方法的作用是获取当前组件实例的边界框。通过调用该方法,可以确定该组件在三维空间中的边界范围,从而进行一些与碰撞检测、
// 渲染或布局相关的操作。
@Override
public BoundingBox getInstanceBoundingBox() {
BoundingBox box = new BoundingBox();
@ -416,7 +378,6 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
*
* @return radius of the underlying BodyComponent or 0 if none exists.
*/
// 这个方法用于获取鳍组件所在的主体组件BodyComponent的半径。
public double getBodyRadius() {
RocketComponent s;
@ -430,14 +391,12 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
}
return 0;
}
// 方法的作用是获取当前组件实例的数量。
@Override
public int getInstanceCount() {
return getFinCount();
}
// 方法的作用是设置当前组件实例的数量,并且通过遍历监听器列表,将新的数量也传递给类型为 TubeFinSet 的监听器对象。
@Override
public void setInstanceCount(int newCount) {
for (RocketComponent listener : configListeners) {
@ -449,26 +408,22 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
setFinCount(newCount);
}
// 方法的作用是根据当前组件实例的数量生成一个模式名称字符串。
@Override
public String getPatternName() {
return (this.getInstanceCount() + "-tubefin-ring");
}
// 方法的作用是计算组件的外接圆半径。这个方法可能用于组件布局、碰撞检测或其他需要考虑组件尺寸的操作中。
@Override
public double getBoundingRadius() {
return getBodyRadius() + getOuterRadius();
}
// 方法的作用是根据给定的方法和半径值来设置组件的半径。
@Override
public void setRadius(RadiusMethod method, double radius) {
// TODO Auto-generated method stub
}
// 方法的作用是设置组件的角度偏移量,并更新相应的变换矩阵和监听器状态。
@Override
public void setAngleOffset(double angleRadians) {
for (RocketComponent listener : configListeners) {
@ -491,19 +446,16 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
// 方法的作用是返回组件当前使用的角度计算方法。
@Override
public AngleMethod getAngleMethod() {
return this.angleMethod;
}
// 方法的作用是返回组件当前的角度偏移量。
@Override
public double getAngleOffset() {
return this.firstFinOffsetRadians;
}
// 方法的作用是设置组件的角度计算方法,并更新相应的监听器状态。
@Override
public void setAngleMethod(AngleMethod newAngleMethod) {
for (RocketComponent listener : configListeners) {
@ -517,13 +469,11 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
// 方法的作用是计算每个组件实例之间的角度增量。
@Override
public double getInstanceAngleIncrement() {
return ( 2*Math.PI / getFinCount());
}
// 方法的作用是计算并返回每个组件实例的角度数组。
@Override
public double[] getInstanceAngles() {
final double angleIncrementRadians = getInstanceAngleIncrement();
@ -536,8 +486,7 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
return result;
}
// 方法的作用是计算并返回每个组件实例的偏移坐标数组。
@Override
public Coordinate[] getInstanceOffsets() {
checkState();
@ -570,13 +519,11 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
}
// 方法的作用是返回内部颜色组件处理器的实例。
@Override
public InsideColorComponentHandler getInsideColorComponentHandler() {
return this.insideColorComponentHandler;
}
// 方法的作用是设置内部颜色组件处理器的实例。
@Override
public void setInsideColorComponentHandler(InsideColorComponentHandler handler) {
this.insideColorComponentHandler = handler;

@ -34,50 +34,33 @@ import net.sf.openrocket.util.Pair;
public class BasicEventSimulationEngine implements SimulationEngine {
// Translator对象用于进行国际化和本地化的翻译。
private static final Translator trans = Application.getTranslator();
// Logger对象用于记录日志信息。
private static final Logger log = LoggerFactory.getLogger(BasicEventSimulationEngine.class);
// TODO: MEDIUM: Allow selecting steppers
// SimulationStepper对象用于执行飞行阶段的模拟步进。
private final SimulationStepper flightStepper = new RK4SimulationStepper();
// SimulationStepper对象用于执行着陆阶段的模拟步进。
private final SimulationStepper landingStepper = new BasicLandingStepper();
// SimulationStepper对象用于执行翻滚阶段的模拟步进。
private final SimulationStepper tumbleStepper = new BasicTumbleStepper();
// GroundStepper对象用于执行地面阶段的模拟步进。
private final SimulationStepper groundStepper = new GroundStepper();
// Constant holding 20 degrees in radians. This is the AOA condition
// necessary to transition to tumbling.
// 表示转换为翻滚状态所需的攻角条件以弧度表示这里是20度。
private final static double AOA_TUMBLE_CONDITION = Math.PI / 9.0;
// The thrust must be below this value for the transition to tumbling.
// TODO HIGH: this is an arbitrary value
// 表示转换为翻滚状态所需的推力条件,该值是一个任意设定的阈值。
private final static double THRUST_TUMBLE_CONDITION = 0.01;
// 当前使用的SimulationStepper对象。
private SimulationStepper currentStepper;
// 当前的SimulationStatus对象表示当前的模拟状态。
private SimulationStatus currentStatus;
// FlightConfigurationId对象表示飞行配置的ID。
private FlightConfigurationId fcid;
// this is just a list of simulation branches to
// 一个双端队列Deque存储待模拟的分支的SimulationStatus对象。
// this is just a list of simulation branches to
Deque<SimulationStatus> toSimulate = new ArrayDeque<SimulationStatus>();
// FlightData对象表示飞行数据。
FlightData flightData;
@Override
@ -157,9 +140,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
return flightData;
}
// 根据给定的火箭配置和仿真条件模拟火箭的飞行过程并生成FlightData对象该对象将包含模拟期间收集到的所有数据例如高度、
// 速度、加速度等,以用于进一步的数据分析和可视化。
private FlightDataBranch simulateLoop() throws SimulationException {
// Initialize the simulation. We'll use the flight stepper unless we're already on the ground
@ -315,13 +296,6 @@ public class BasicEventSimulationEngine implements SimulationEngine {
* Each event that has occurred before or at the current simulation time is
* processed. Suitable events are also added to the flight data.
*/
// 这段注释描述方法用于处理飞行过程中从事件队列中发生的事件。在当前模拟时间之前或等于当前模拟时间的每个事件都会被处理。
// 适当的事件也会被添加到飞行数据中。
// 换句话说,这个方法负责处理飞行过程中发生的事件。它从事件队列中获取事件,并根据事件的类型和发生的时间来执行相应的操作。
// 这些操作可能包括更新飞行状态、调整飞行参数、记录事件信息等。
// 该方法是一个模拟火箭飞行事件的引擎。它接收一个火箭的当前状态currentStatus和一系列事件events并根据不同的事件
// 类型执行相应的操作。
private boolean handleEvents() throws SimulationException {
boolean ret = true;
FlightEvent event;
@ -659,7 +633,6 @@ public class BasicEventSimulationEngine implements SimulationEngine {
*
* @param event the event to add to the queue.
*/
// 将飞行事件添加到事件队列中,除非监听器阻止添加。
private void addEvent(FlightEvent event) throws SimulationException {
if (SimulationListenerHelper.fireAddFlightEvent(currentStatus, event)) {
currentStatus.getEventQueue().add(event);
@ -675,7 +648,6 @@ public class BasicEventSimulationEngine implements SimulationEngine {
*
* @return the flight event to handle, or null
*/
// 获取下一个要处理的飞行事件如果没有更多的事件需要处理则返回null。
private FlightEvent nextEvent() {
EventQueue queue = currentStatus.getEventQueue();
FlightEvent event = queue.peek();
@ -695,7 +667,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
}
// 检查模拟过程中是否出现NaN值不是一个数字,如果存在NaN值则记录错误日志并抛出。
private void checkNaN() throws SimulationException {
double d = 0;
boolean b = false;
@ -719,9 +691,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
throw new SimulationException(trans.get("BasicEventSimulationEngine.error.NaNResult"));
}
}
// 计算滑翔时间。该方法会克隆当前状态的模拟条件并添加OptimumCoastListener监听器。然后创建一个新的
// BasicEventSimulationEngine实例并使用克隆的条件进行模拟。最后返回模拟的飞行数据。
private FlightData computeCoastTime() {
try {
SimulationConditions conds = currentStatus.getSimulationConditions().clone();

@ -13,19 +13,15 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BasicLandingStepper extends AbstractSimulationStepper {
// 一个Logger对象用于在代码中记录日志信息。
private static final Logger log = LoggerFactory.getLogger(BasicLandingStepper.class);
// 一个常量表示恢复recovery过程的时间步长。
private static final double RECOVERY_TIME_STEP = 0.5;
// 方法的作用是初始化模拟状态,并返回初始化后的状态。
@Override
public SimulationStatus initialize(SimulationStatus status) {
return status;
}
// 该方法的作用是在模拟过程中更新火箭的状态,并计算火箭的位置、速度、加速度等参数。
@Override
public void step(SimulationStatus status, double maxTimeStep) throws SimulationException {
double totalCD = 0;

@ -15,19 +15,12 @@ import net.sf.openrocket.rocketcomponent.SymmetricComponent;
public class BasicTumbleStatus extends SimulationStatus {
// Magic constants from techdoc.pdf
// 表示翼型阻力系数Fin Drag Coefficient是一个来自techdoc.pdf的魔法常数。它用于计算由翼型产生的阻力。
private final static double cDFin = 1.42;
// 表示身体阻力系数Body Drag Coefficient也是一个来自techdoc.pdf的魔法常数。它用于计算由火箭身体产生的阻力。
private final static double cDBt = 0.56;
// Fin efficiency. Index is number of fins. The 0th entry is arbitrary and used to
// offset the indexes so finEff[1] is the coefficient for one fin from the table in techdoc.pdf
// 表示翼型效率Fin Efficiency。这是一个数组索引表示翼型的数量数组中的值表示对应数量的翼型的效率系数。
// 数组的第一个元素是任意的并用于偏移索引使得finEff[1]表示techdoc.pdf中翼型数量为1时的系数。
private final static double[] finEff = { 0.0, 0.5, 1.0, 1.41, 1.81, 1.73, 1.90, 1.85 };
// 表示总阻力Drag。用于存储火箭的总阻力。它是根据翼型阻力系数、身体阻力系数和翼型效率等因素计算得出的。
private final double drag;
public BasicTumbleStatus(FlightConfiguration configuration,
@ -44,14 +37,12 @@ public class BasicTumbleStatus extends SimulationStatus {
this.drag = computeTumbleDrag();
}
}
// 方法返回火箭在翻滚状态下的总阻力。它只是返回drag变量的值即computeTumbleDrag()方法计算得出的总阻力。
public double getTumbleDrag() {
return drag;
}
// 方法计算火箭在翻滚状态下的总阻力。它根据火箭的构造来计算总阻力。
private double computeTumbleDrag() {
// Computed based on Sampo's experimentation as documented in the pdf.

@ -1,77 +1,77 @@
package net.sf.openrocket.simulation;
import net.sf.openrocket.startup.Preferences;
import com.google.inject.Inject;
public class DefaultSimulationOptionFactory {
@Inject
private final Preferences prefs;
public static final String SIMCONDITION_WIND_SPEED = "SimConditionWindSpeed";
public static final String SIMCONDITION_WIND_STDDEV = "SimConditionWindStdDev";
public static final String SIMCONDITION_WIND_TURB = "SimConditionWindTurb";
public static final String SIMCONDITION_SITE_LAT = "SimConditionSiteLat";
public static final String SIMCONDITION_SITE_LON = "SimConditionSiteLon";
public static final String SIMCONDITION_SITE_ALT = "SimConditionSiteAlt";
public static final String SIMCONDITION_ATMOS_STD = "SimConditionsAtmosStd";
public static final String SIMCONDITION_ATMOS_TEMP = "SimConditionsAtmosTemp";
public static final String SIMCONDITION_ATMOS_PRESSURE = "SimConditionsAtmosPres";
public static final String SIMCONDITION_ROD_INTO_WIND = "SimConditionsRodIntoWind";
public static final String SIMCONDITION_ROD_LENGTH = "SimConditionsRodLength";
public static final String SIMCONDITION_ROD_ANGLE = "SimConditionsRodAngle";
public static final String SIMCONDITION_ROD_DIRECTION = "SimConditionsRodDirection";
public DefaultSimulationOptionFactory(Preferences prefs) {
this.prefs = prefs;
}
public DefaultSimulationOptionFactory() {
prefs = null;
}
public SimulationOptions getDefault() {
SimulationOptions defaults = new SimulationOptions();
if (prefs != null) {
defaults.setWindSpeedAverage(prefs.getDouble(SIMCONDITION_WIND_SPEED, defaults.getWindSpeedAverage()));
defaults.setWindSpeedDeviation(prefs.getDouble(SIMCONDITION_WIND_STDDEV, defaults.getWindSpeedDeviation()));
defaults.setWindTurbulenceIntensity(prefs.getDouble(SIMCONDITION_WIND_TURB, defaults.getWindTurbulenceIntensity()));
defaults.setLaunchLatitude(prefs.getDouble(SIMCONDITION_SITE_LAT, defaults.getLaunchLatitude()));
defaults.setLaunchLongitude(prefs.getDouble(SIMCONDITION_SITE_LON, defaults.getLaunchLongitude()));
defaults.setLaunchAltitude(prefs.getDouble(SIMCONDITION_SITE_ALT, defaults.getLaunchAltitude()));
defaults.setISAAtmosphere(prefs.getBoolean(SIMCONDITION_ATMOS_STD, defaults.isISAAtmosphere()));
defaults.setLaunchTemperature(prefs.getDouble(SIMCONDITION_ATMOS_TEMP, defaults.getLaunchTemperature()));
defaults.setLaunchPressure(prefs.getDouble(SIMCONDITION_ATMOS_PRESSURE, defaults.getLaunchTemperature()));
defaults.setLaunchIntoWind(prefs.getBoolean(SIMCONDITION_ROD_INTO_WIND, defaults.getLaunchIntoWind()));
defaults.setLaunchRodLength(prefs.getDouble(SIMCONDITION_ROD_LENGTH, defaults.getLaunchRodLength()));
defaults.setLaunchRodAngle(prefs.getDouble(SIMCONDITION_ROD_ANGLE, defaults.getLaunchRodAngle()));
defaults.setLaunchRodDirection(prefs.getDouble(SIMCONDITION_ROD_DIRECTION, defaults.getLaunchRodDirection()));
}
return defaults;
}
public void saveDefault(SimulationOptions newDefaults) {
prefs.putDouble(SIMCONDITION_WIND_SPEED, newDefaults.getWindSpeedAverage());
prefs.putDouble(SIMCONDITION_WIND_STDDEV, newDefaults.getWindSpeedDeviation());
prefs.putDouble(SIMCONDITION_WIND_TURB, newDefaults.getWindTurbulenceIntensity());
prefs.putDouble(SIMCONDITION_SITE_LAT, newDefaults.getLaunchLatitude());
prefs.putDouble(SIMCONDITION_SITE_LON, newDefaults.getLaunchLongitude());
prefs.putDouble(SIMCONDITION_SITE_ALT, newDefaults.getLaunchAltitude());
prefs.putBoolean(SIMCONDITION_ATMOS_STD, newDefaults.isISAAtmosphere());
prefs.putDouble(SIMCONDITION_ATMOS_TEMP, newDefaults.getLaunchTemperature());
prefs.putDouble(SIMCONDITION_ATMOS_PRESSURE, newDefaults.getLaunchPressure());
prefs.putBoolean(SIMCONDITION_ROD_INTO_WIND, newDefaults.getLaunchIntoWind());
prefs.putDouble(SIMCONDITION_ROD_LENGTH, newDefaults.getLaunchRodLength());
prefs.putDouble(SIMCONDITION_ROD_ANGLE, newDefaults.getLaunchRodAngle());
prefs.putDouble(SIMCONDITION_ROD_DIRECTION, newDefaults.getLaunchRodDirection());
}
}
package net.sf.openrocket.simulation;
import net.sf.openrocket.startup.Preferences;
import com.google.inject.Inject;
public class DefaultSimulationOptionFactory {
@Inject
private final Preferences prefs;
public static final String SIMCONDITION_WIND_SPEED = "SimConditionWindSpeed";
public static final String SIMCONDITION_WIND_STDDEV = "SimConditionWindStdDev";
public static final String SIMCONDITION_WIND_TURB = "SimConditionWindTurb";
public static final String SIMCONDITION_SITE_LAT = "SimConditionSiteLat";
public static final String SIMCONDITION_SITE_LON = "SimConditionSiteLon";
public static final String SIMCONDITION_SITE_ALT = "SimConditionSiteAlt";
public static final String SIMCONDITION_ATMOS_STD = "SimConditionsAtmosStd";
public static final String SIMCONDITION_ATMOS_TEMP = "SimConditionsAtmosTemp";
public static final String SIMCONDITION_ATMOS_PRESSURE = "SimConditionsAtmosPres";
public static final String SIMCONDITION_ROD_INTO_WIND = "SimConditionsRodIntoWind";
public static final String SIMCONDITION_ROD_LENGTH = "SimConditionsRodLength";
public static final String SIMCONDITION_ROD_ANGLE = "SimConditionsRodAngle";
public static final String SIMCONDITION_ROD_DIRECTION = "SimConditionsRodDirection";
public DefaultSimulationOptionFactory(Preferences prefs) {
this.prefs = prefs;
}
public DefaultSimulationOptionFactory() {
prefs = null;
}
public SimulationOptions getDefault() {
SimulationOptions defaults = new SimulationOptions();
if (prefs != null) {
defaults.setWindSpeedAverage(prefs.getDouble(SIMCONDITION_WIND_SPEED, defaults.getWindSpeedAverage()));
defaults.setWindSpeedDeviation(prefs.getDouble(SIMCONDITION_WIND_STDDEV, defaults.getWindSpeedDeviation()));
defaults.setWindTurbulenceIntensity(prefs.getDouble(SIMCONDITION_WIND_TURB, defaults.getWindTurbulenceIntensity()));
defaults.setLaunchLatitude(prefs.getDouble(SIMCONDITION_SITE_LAT, defaults.getLaunchLatitude()));
defaults.setLaunchLongitude(prefs.getDouble(SIMCONDITION_SITE_LON, defaults.getLaunchLongitude()));
defaults.setLaunchAltitude(prefs.getDouble(SIMCONDITION_SITE_ALT, defaults.getLaunchAltitude()));
defaults.setISAAtmosphere(prefs.getBoolean(SIMCONDITION_ATMOS_STD, defaults.isISAAtmosphere()));
defaults.setLaunchTemperature(prefs.getDouble(SIMCONDITION_ATMOS_TEMP, defaults.getLaunchTemperature()));
defaults.setLaunchPressure(prefs.getDouble(SIMCONDITION_ATMOS_PRESSURE, defaults.getLaunchTemperature()));
defaults.setLaunchIntoWind(prefs.getBoolean(SIMCONDITION_ROD_INTO_WIND, defaults.getLaunchIntoWind()));
defaults.setLaunchRodLength(prefs.getDouble(SIMCONDITION_ROD_LENGTH, defaults.getLaunchRodLength()));
defaults.setLaunchRodAngle(prefs.getDouble(SIMCONDITION_ROD_ANGLE, defaults.getLaunchRodAngle()));
defaults.setLaunchRodDirection(prefs.getDouble(SIMCONDITION_ROD_DIRECTION, defaults.getLaunchRodDirection()));
}
return defaults;
}
public void saveDefault(SimulationOptions newDefaults) {
prefs.putDouble(SIMCONDITION_WIND_SPEED, newDefaults.getWindSpeedAverage());
prefs.putDouble(SIMCONDITION_WIND_STDDEV, newDefaults.getWindSpeedDeviation());
prefs.putDouble(SIMCONDITION_WIND_TURB, newDefaults.getWindTurbulenceIntensity());
prefs.putDouble(SIMCONDITION_SITE_LAT, newDefaults.getLaunchLatitude());
prefs.putDouble(SIMCONDITION_SITE_LON, newDefaults.getLaunchLongitude());
prefs.putDouble(SIMCONDITION_SITE_ALT, newDefaults.getLaunchAltitude());
prefs.putBoolean(SIMCONDITION_ATMOS_STD, newDefaults.isISAAtmosphere());
prefs.putDouble(SIMCONDITION_ATMOS_TEMP, newDefaults.getLaunchTemperature());
prefs.putDouble(SIMCONDITION_ATMOS_PRESSURE, newDefaults.getLaunchPressure());
prefs.putBoolean(SIMCONDITION_ROD_INTO_WIND, newDefaults.getLaunchIntoWind());
prefs.putDouble(SIMCONDITION_ROD_LENGTH, newDefaults.getLaunchRodLength());
prefs.putDouble(SIMCONDITION_ROD_ANGLE, newDefaults.getLaunchRodAngle());
prefs.putDouble(SIMCONDITION_ROD_DIRECTION, newDefaults.getLaunchRodDirection());
}
}

@ -20,85 +20,70 @@ public class FlightEvent implements Comparable<FlightEvent> {
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
// 这段代码定义了一个枚举类型(Type),用于表示飞行事件的类型
public enum Type {
/**
* Rocket launch.
*/
// 火箭发射事件。
LAUNCH(trans.get("FlightEvent.Type.LAUNCH")),
/**
* Ignition of a motor. Source is the motor mount the motor of which has ignited,
* and the data is the MotorId of the motor instance.
*/
// 点火事件,表示点火引燃了一个发动机。
IGNITION(trans.get("FlightEvent.Type.IGNITION")),
/**
* When the motor has lifted off the ground.
*/
// 发动机离地事件,表示发动机离开了地面。
LIFTOFF(trans.get("FlightEvent.Type.LIFTOFF")),
/**
* Launch rod has been cleared.
*/
// 发射杆清除事件,表示发射杆已经被清除。
LAUNCHROD(trans.get("FlightEvent.Type.LAUNCHROD")),
/**
* Burnout of a motor. Source is the motor mount the motor of which has burnt out,
* and the data is the MotorId of the motor instance.
*/
// 发动机燃烧结束事件,表示一个发动机燃烧完毕。
BURNOUT(trans.get("FlightEvent.Type.BURNOUT")),
/**
* Ejection charge of a motor fired. Source is the motor mount the motor of
* which has exploded its ejection charge, and data is the MotorId of the motor instance.
*/
// 发动机喷射药事件,表示发动机的喷射药爆炸了。
EJECTION_CHARGE(trans.get("FlightEvent.Type.EJECTION_CHARGE")),
/**
* Separation of a stage. Source is the stage which is being separated from the upper stages.
*/
// 分离阶段事件,表示一个阶段被从上层阶段分离。
STAGE_SEPARATION(trans.get("FlightEvent.Type.STAGE_SEPARATION")),
/**
* Apogee has been reached.
*/
// 顶点高度事件,表示火箭达到了最高点。
APOGEE(trans.get("FlightEvent.Type.APOGEE")),
/**
* Opening of a recovery device. Source is the RecoveryComponent which has opened.
*/
// 恢复设备展开事件,表示恢复组件(如降落伞)已经展开。
RECOVERY_DEVICE_DEPLOYMENT(trans.get("FlightEvent.Type.RECOVERY_DEVICE_DEPLOYMENT")),
/**
* Ground has been hit after flight.
*/
// 着地事件,表示火箭在飞行后着陆。
GROUND_HIT(trans.get("FlightEvent.Type.GROUND_HIT")),
/**
* End of simulation. Placing this to the queue will end the simulation.
*/
// 拟结束事件,将该事件放入队列将结束模拟。
SIMULATION_END(trans.get("FlightEvent.Type.SIMULATION_END")),
/**
* A change in altitude has occurred. Data is a <code>Pair<Double,Double></code>
* which contains the old and new altitudes.
*/
// 高度变化事件,表示火箭的高度发生了变化。
ALTITUDE(trans.get("FlightEvent.Type.ALTITUDE")),
/**
* The rocket begins to tumble.
*/
// 火箭开始翻滚事件。
TUMBLE(trans.get("FlightEvent.Type.TUMBLE")),
/**
* Simulation aborted
*/
// 模拟异常事件,表示模拟过程中出现了异常。
EXCEPTION(trans.get("FlightEvent.Type.EXCEPTION"));
private final String name;
@ -164,7 +149,6 @@ public class FlightEvent implements Comparable<FlightEvent> {
* sorting is performed on stages; lower (numerically higher) stage first. Tertiary
* sorting is performed based on the event type ordinal.
*/
// 用于比较两个FlightEvent对象的顺序。
@Override
public int compareTo(FlightEvent o) {
@ -205,7 +189,6 @@ public class FlightEvent implements Comparable<FlightEvent> {
*
* @return
*/
// 方法用于验证FlightEvent对象的状态是否符合规范以确保在OpenRocket的模拟过程中不会出现由用户行为引起的异常状态。
public void validate(){
if(Double.isNaN(this.time)){
throw new IllegalStateException(type.name()+" event has a NaN time!");

@ -10,15 +10,13 @@ import net.sf.openrocket.util.Coordinate;
public class GroundStepper extends AbstractSimulationStepper {
private static final Logger log = LoggerFactory.getLogger(GroundStepper.class);
// 初始化GroundStepper对象
@Override
public SimulationStatus initialize(SimulationStatus status) {
log.trace("initializing GroundStepper");
return status;
}
// 执行模拟的一步。这个方法在每个时间步长内被调用,用于更新模拟状态。
@Override
public void step(SimulationStatus status, double timeStep) throws SimulationException {
log.trace("step: position=" + status.getRocketPosition() + ", velocity=" + status.getRocketVelocity());

@ -26,93 +26,71 @@ import net.sf.openrocket.util.WorldCoordinate;
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public class SimulationConditions implements Monitorable, Cloneable {
// 父级模拟对象。
private Simulation simulation; // The parent simulation
// 发射架长度。
private double launchRodLength = 1;
// 发射架角度以弧度为单位大于等于0。
/** Launch rod angle >= 0, radians from vertical */
private double launchRodAngle = 0;
// 发射架方向以北为0度顺时针方向为正。
/** Launch rod direction, 0 = north */
private double launchRodDirection = 0;
// 发射地点的经纬度和高度。
// Launch site location (lat, lon, alt)
private WorldCoordinate launchSite = new WorldCoordinate(0, 0, 0);
// 发射位置在模拟坐标系中的坐标。
// Launch location in simulation coordinates (normally always 0, air-start would override this)
private Coordinate launchPosition = Coordinate.NUL;
// 发射速度在模拟坐标系中的坐标。
private Coordinate launchVelocity = Coordinate.NUL;
// 大地测量计算策略。
private GeodeticComputationStrategy geodeticComputation = GeodeticComputationStrategy.SPHERICAL;
// 风模型。
private WindModel windModel;
// 大气模型。
private AtmosphericModel atmosphericModel;
// 重力模型。
private GravityModel gravityModel;
// 空气动力学计算器。
private AerodynamicCalculator aerodynamicCalculator;
// 质量计算器。
private MassCalculator massCalculator;
// 时间步长。
private double timeStep = RK4SimulationStepper.RECOMMENDED_TIME_STEP;
// 角度步长。
private double maximumAngleStep = RK4SimulationStepper.RECOMMENDED_ANGLE_STEP;
// 是否计算额外数据。
/* Whether to calculate additional data or only primary simulation figures */
private boolean calculateExtras = true;
// 模拟监听器列表。
private List<SimulationListener> simulationListeners = new ArrayList<SimulationListener>();
// 随机种子。
private int randomSeed = 0;
// 模型ID。
private int modID = 0;
// 附加模型ID。
private int modIDadd = 0;
// 获取当前的空气动力学计算器。
public AerodynamicCalculator getAerodynamicCalculator() {
return aerodynamicCalculator;
}
// 设置空气动力学计算器用于计算火箭的空气动力学参数。在设置新的计算器时会更新模型ID和附加模型ID。
public void setAerodynamicCalculator(AerodynamicCalculator aerodynamicCalculator) {
if (this.aerodynamicCalculator != null)
this.modIDadd += this.aerodynamicCalculator.getModID();
this.modID++;
this.aerodynamicCalculator = aerodynamicCalculator;
}
// 获取当前的质量计算器。
public MassCalculator getMassCalculator() {
return massCalculator;
}
// 设置质量计算器用于计算火箭的质量参数。在设置新的计算器时会更新模型ID和附加模型ID。
public void setMassCalculator(MassCalculator massCalculator) {
if (this.massCalculator != null)
this.modIDadd += this.massCalculator.getModID();
@ -120,69 +98,58 @@ public class SimulationConditions implements Monitorable, Cloneable {
this.massCalculator = massCalculator;
}
// 获取当前模拟对象的火箭。
public Rocket getRocket() {
return simulation.getRocket();
}
// 获取当前模拟对象的火箭发动机配置ID。
public FlightConfigurationId getMotorConfigurationID() {
return simulation.getId();
}
// 获取当前模拟对象的火箭飞行配置ID。
public FlightConfigurationId getFlightConfigurationID() {
return simulation.getId();
}
// 获取发射架长度。
public double getLaunchRodLength() {
return launchRodLength;
}
// 设置发射架长度。
public void setLaunchRodLength(double launchRodLength) {
this.launchRodLength = launchRodLength;
this.modID++;
}
// 获取发射架角度。
public double getLaunchRodAngle() {
return launchRodAngle;
}
// 设置发射架角度。
public void setLaunchRodAngle(double launchRodAngle) {
this.launchRodAngle = launchRodAngle;
this.modID++;
}
// 获取发射架方向。
public double getLaunchRodDirection() {
return launchRodDirection;
}
// 设置发射架方向。
public void setLaunchRodDirection(double launchRodDirection) {
this.launchRodDirection = launchRodDirection;
this.modID++;
}
// 获取当前模拟对象的发射场地点。
public WorldCoordinate getLaunchSite() {
return this.launchSite;
}
// 设置当前模拟对象的发射场地点。在设置新的场地点时会更新模型ID和附加模型ID。
public void setLaunchSite(WorldCoordinate site) {
if (this.launchSite.equals(site))
return;
@ -190,40 +157,34 @@ public class SimulationConditions implements Monitorable, Cloneable {
this.modID++;
}
// 获取当前模拟对象的发射位置。
public Coordinate getLaunchPosition() {
return launchPosition;
}
// 设置当前模拟对象的发射位置。在设置新的发射位置时会更新模型ID和附加模型ID。
public void setLaunchPosition(Coordinate launchPosition) {
if (this.launchPosition.equals(launchPosition))
return;
this.launchPosition = launchPosition;
this.modID++;
}
// 获取当前模拟对象的发射速度。
public Coordinate getLaunchVelocity() {
return launchVelocity;
}
// 置当前模拟对象的发射速度。在设置新的发射速度时会更新模型ID和附加模型ID。
public void setLaunchVelocity(Coordinate launchVelocity) {
if (this.launchVelocity.equals(launchVelocity))
return;
this.launchVelocity = launchVelocity;
this.modID++;
}
// 获取当前使用的大地计算策略。
public GeodeticComputationStrategy getGeodeticComputation() {
return geodeticComputation;
}
// 设置当前使用的大地计算策略。在设置新的计算策略时会更新模型ID和附加模型ID。
public void setGeodeticComputation(GeodeticComputationStrategy geodeticComputation) {
if (this.geodeticComputation == geodeticComputation)
return;
@ -234,14 +195,12 @@ public class SimulationConditions implements Monitorable, Cloneable {
this.modID++;
}
// 获取当前使用的风模型。
public WindModel getWindModel() {
return windModel;
}
// 设置当前使用的风模型。在设置新的风模型时会更新模型ID和附加模型ID。
public void setWindModel(WindModel windModel) {
if (this.windModel != null)
this.modIDadd += this.windModel.getModID();
@ -249,15 +208,12 @@ public class SimulationConditions implements Monitorable, Cloneable {
this.windModel = windModel;
}
// 获取当前使用的大气模型。
public AtmosphericModel getAtmosphericModel() {
return atmosphericModel;
}
// 设置大气模型。通过传入一个AtmosphericModel对象设置当前模拟对象使用的大气模型。
// 在设置新的大气模型时会更新模型ID和附加模型ID。
public void setAtmosphericModel(AtmosphericModel atmosphericModel) {
if (this.atmosphericModel != null)
this.modIDadd += this.atmosphericModel.getModID();
@ -265,15 +221,12 @@ public class SimulationConditions implements Monitorable, Cloneable {
this.atmosphericModel = atmosphericModel;
}
// 获取重力模型。返回当前模拟对象使用的重力模型。
public GravityModel getGravityModel() {
return gravityModel;
}
// 设置重力模型。通过传入一个GravityModel对象设置当前模拟对象使用的重力模型。
// 在设置新的重力模型时会更新模型ID和附加模型ID。
public void setGravityModel(GravityModel gravityModel) {
//if (this.gravityModel != null)
// this.modIDadd += this.gravityModel.getModID();
@ -281,78 +234,65 @@ public class SimulationConditions implements Monitorable, Cloneable {
this.gravityModel = gravityModel;
}
// 获取时间步长。返回当前模拟对象的时间步长。
public double getTimeStep() {
return timeStep;
}
// 设置时间步长。通过传入一个double类型的参数设置当前模拟对象的时间步长。在设置新的时间步长时会更新模型ID。
public void setTimeStep(double timeStep) {
this.timeStep = timeStep;
this.modID++;
}
// 获取最大角度步长。返回当前模拟对象的最大角度步长。
public double getMaximumAngleStep() {
return maximumAngleStep;
}
// 设置最大角度步长。通过传入一个double类型的参数设置当前模拟对象的最大角度步长。在设置新的最大角度步长时会更新模型ID。
public void setMaximumAngleStep(double maximumAngle) {
this.maximumAngleStep = maximumAngle;
this.modID++;
}
// 判断是否计算额外信息。
public boolean isCalculateExtras() {
return calculateExtras;
}
// 设置是否计算额外信息。
public void setCalculateExtras(boolean calculateExtras) {
this.calculateExtras = calculateExtras;
this.modID++;
}
// 获取随机种子。
public int getRandomSeed() {
return randomSeed;
}
// 设置随机种子。通过传入一个整数参数设置当前模拟对象的随机种子。在设置新的随机种子时会更新模型ID。
public void setRandomSeed(int randomSeed) {
this.randomSeed = randomSeed;
this.modID++;
}
// 设置模拟对象。通过传入一个Simulation对象设置当前SimulationConditions对象的模拟对象。
public void setSimulation(Simulation sim) {
this.simulation = sim;
}
// 获取模拟对象。返回当前SimulationConditions对象的模拟对象。
public Simulation getSimulation() {
return this.simulation;
}
// 获取模拟监听器列表。返回一个包含所有模拟监听器的列表。
// TODO: HIGH: Make cleaner
public List<SimulationListener> getSimulationListenerList() {
return simulationListeners;
}
// 获取模拟条件的模型ID。
// 返回一个整数表示当前模拟对象的模型ID该ID由多个子模型的ID相加得到包括大气模型、重力模型、风模型、质量计算器、空气动力学计算器等。
@Override
public int getModID() {
//return (modID + modIDadd + rocket.getModID() + windModel.getModID() + atmosphericModel.getModID() +
@ -361,9 +301,7 @@ public class SimulationConditions implements Monitorable, Cloneable {
aerodynamicCalculator.getModID() + massCalculator.getModID());
}
// 克隆模拟条件对象。在克隆过程中除了模型ID和附加模型ID之外其他所有属性都被克隆到新对象中。
// 同时,还会对所有的模拟监听器进行深度克隆,以确保新对象与原对象之间没有任何关联。
@Override
public SimulationConditions clone() {
try {

@ -33,116 +33,84 @@ import net.sf.openrocket.util.WorldCoordinate;
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public class SimulationOptions implements ChangeSource, Cloneable {
@SuppressWarnings("unused")
// 一个日志记录器,用于在需要时记录模拟选项的相关信息。
private static final Logger log = LoggerFactory.getLogger(SimulationOptions.class);
// 最大发射杆角度。表示发射杆允许的最大角度,以弧度为单位。
public static final double MAX_LAUNCH_ROD_ANGLE = Math.PI / 3;
/**
* The ISA standard atmosphere.
*/
// ISA标准大气模型。表示使用的大气模型这里是ISA标准大气模型。
private static final AtmosphericModel ISA_ATMOSPHERIC_MODEL = new ExtendedISAModel();
// 偏好设置对象。用于获取和保存模拟选项的偏好设置。
protected final Preferences preferences = Application.getPreferences();
/*
* NOTE: When adding/modifying parameters, they must also be added to the
* equals and copyFrom methods!!
*/
// 这段注释是提醒在添加或修改参数时,必须同步更新 equals 和 copyFrom 方法。这是为了确保对象的相等性比较和属性复制的一致性。
// 发射杆长度。表示发射杆的长度,以米为单位。
private double launchRodLength = preferences.getDouble(Preferences.LAUNCH_ROD_LENGTH, 1);
// 是否逆风发射。表示是否选择逆风发射火箭。
private boolean launchIntoWind = preferences.getBoolean(Preferences.LAUNCH_INTO_WIND, true);
// 发射杆角度。表示发射杆的角度,以弧度为单位。
private double launchRodAngle = preferences.getDouble(Preferences.LAUNCH_ROD_ANGLE, 0);
// 表示风的方向,以弧度为单位。
private double windDirection = preferences.getDouble(Preferences.WIND_DIRECTION, Math.PI / 2);
// 发射杆方向。表示发射杆的方向,以弧度为单位。
private double launchRodDirection = preferences.getDouble(Preferences.LAUNCH_ROD_DIRECTION, Math.PI / 2);
// 风速平均值。表示风速的平均值,以米/秒为单位。
private double windAverage = preferences.getDouble(Preferences.WIND_AVERAGE, 2.0);
// 风速湍流。表示风速的湍流程度。
private double windTurbulence = preferences.getDouble(Preferences.WIND_TURBULENCE, 0.1);
/*
* SimulationOptions maintains the launch site parameters as separate double values,
* and converts them into a WorldCoordinate when converting to SimulationConditions.
*/
// SimulationOptions 类用于维护发射场地参数,这些参数以独立的双精度值进行存储,并在转换为 SimulationConditions 对象时将
// 它们转换为 WorldCoordinate 对象。
// 发射高度。表示发射地点的海拔高度,以米为单位。
private double launchAltitude = preferences.getDouble(Preferences.LAUNCH_ALTITUDE, 0);
// 发射纬度。表示发射地点的纬度,以度为单位。
private double launchLatitude = preferences.getDouble(Preferences.LAUNCH_LATITUDE, 28.61);
// 发射经度。表示发射地点的经度,以度为单位。
private double launchLongitude = preferences.getDouble(Preferences.LAUNCH_LONGITUDE, -80.60);
// 大地测量计算策略。表示使用的大地测量计算策略。
private GeodeticComputationStrategy geodeticComputation = GeodeticComputationStrategy.SPHERICAL;
// 是否使用ISA标准。表示是否使用ISA标准的大气模型。
private boolean useISA = preferences.getBoolean(Preferences.LAUNCH_USE_ISA, true);
// 发射温度。表示发射地点的温度,以摄氏度为单位。
private double launchTemperature = preferences.getDouble(Preferences.LAUNCH_TEMPERATURE, ExtendedISAModel.STANDARD_TEMPERATURE);
// 发射压力。表示发射地点的气压,以帕斯卡为单位。
private double launchPressure = preferences.getDouble(Preferences.LAUNCH_PRESSURE, ExtendedISAModel.STANDARD_PRESSURE);
// 时间步长。表示模拟的时间步长,以秒为单位。
private double timeStep = preferences.getDouble(Preferences.SIMULATION_TIME_STEP, RK4SimulationStepper.RECOMMENDED_TIME_STEP);
// 最大角度。表示模拟过程中的最大角度步长,以弧度为单位。
private double maximumAngle = RK4SimulationStepper.RECOMMENDED_ANGLE_STEP;
// 随机种子。表示用于生成随机数的种子值。
private int randomSeed = new Random().nextInt();
// 是否计算额外参数。表示是否计算额外的模拟参数。
private boolean calculateExtras = true;
// 监听器列表。用于保存模拟选项的监听器对象列表。
private List<EventListener> listeners = new ArrayList<EventListener>();
public SimulationOptions() {
}
// 获取发射杆长度。
public double getLaunchRodLength() {
return launchRodLength;
}
// 设置发射杆长度。
public void setLaunchRodLength(double launchRodLength) {
if (MathUtil.equals(this.launchRodLength, launchRodLength))
return;
this.launchRodLength = launchRodLength;
}
// 获取是否逆风发射。
public boolean getLaunchIntoWind() {
return launchIntoWind;
}
// 设置是否逆风发射。
public void setLaunchIntoWind(boolean i) {
launchIntoWind = i;
}
// 获取发射杆角度。
public double getLaunchRodAngle() {
return launchRodAngle;
}
// 设置发射杆角度,并对其进行限制,确保其不超过最大发射杆角度。
public void setLaunchRodAngle(double launchRodAngle) {
launchRodAngle = MathUtil.clamp(launchRodAngle, -MAX_LAUNCH_ROD_ANGLE, MAX_LAUNCH_ROD_ANGLE);
if (MathUtil.equals(this.launchRodAngle, launchRodAngle))
@ -151,16 +119,14 @@ public class SimulationOptions implements ChangeSource, Cloneable {
fireChangeEvent();
}
// 获取发射杆方向。如果选择逆风发射,则会自动设置发射杆方向为风向。
public double getLaunchRodDirection() {
if (launchIntoWind) {
this.setLaunchRodDirection(windDirection);
}
return launchRodDirection;
}
// 设置发射杆方向并对其进行限制确保其在0到2π之间。
public void setLaunchRodDirection(double launchRodDirection) {
launchRodDirection = MathUtil.reduce2Pi(launchRodDirection);
if (MathUtil.equals(this.launchRodDirection, launchRodDirection))
@ -170,13 +136,11 @@ public class SimulationOptions implements ChangeSource, Cloneable {
}
// 获取平均风速。
public double getWindSpeedAverage() {
return windAverage;
}
// 设置平均风速并确保其不小于0。
public void setWindSpeedAverage(double windAverage) {
if (MathUtil.equals(this.windAverage, windAverage))
return;
@ -184,14 +148,11 @@ public class SimulationOptions implements ChangeSource, Cloneable {
fireChangeEvent();
}
// 获取风速标准差。风速标准差等于平均风速乘以风湍流强度。
public double getWindSpeedDeviation() {
return windAverage * windTurbulence;
}
// 根据给定的风速标准差设置平均风速和风湍流强度。如果平均风速小于0.1则将平均风速设置为0.1,并根据新的平均风速和风速标准差
// 计算风湍流强度。
public void setWindSpeedDeviation(double windDeviation) {
if (windAverage < 0.1) {
windAverage = 0.1;
@ -205,7 +166,6 @@ public class SimulationOptions implements ChangeSource, Cloneable {
*
* @return the turbulence intensity
*/
// 获取风湍流强度(标准差除以平均值)。
public double getWindTurbulenceIntensity() {
return windTurbulence;
}
@ -215,7 +175,6 @@ public class SimulationOptions implements ChangeSource, Cloneable {
*
* @param intensity the turbulence intensity
*/
// 根据给定的风湍流强度设置风速标准差。该方法不进行相等性检查以确保setWindSpeedDeviation方法能够触发事件。
public void setWindTurbulenceIntensity(double intensity) {
// Does not check equality so that setWindSpeedDeviation can be sure of event firing
this.windTurbulence = intensity;
@ -228,8 +187,7 @@ public class SimulationOptions implements ChangeSource, Cloneable {
*
* @param direction the wind direction
*/
// 设置风向。该方法会将给定的风向值转换为0到2π之间的范围并根据是否选择了"launchIntoWind"选项来设置发射杆的方向。
// 如果新的风向与当前风向相等则不进行任何操作。最后触发change事件。
public void setWindDirection(double direction) {
direction = MathUtil.reduce2Pi(direction);
if (launchIntoWind) {
@ -241,19 +199,16 @@ public class SimulationOptions implements ChangeSource, Cloneable {
fireChangeEvent();
}
// 获取风向。
public double getWindDirection() {
return this.windDirection;
}
// 获取发射高度。
public double getLaunchAltitude() {
return launchAltitude;
}
// 设置发射高度。如果新的发射高度与当前高度相等则不进行任何操作。最后触发change事件。
public void setLaunchAltitude(double altitude) {
if (MathUtil.equals(this.launchAltitude, altitude))
return;
@ -261,14 +216,11 @@ public class SimulationOptions implements ChangeSource, Cloneable {
fireChangeEvent();
}
// 获取发射纬度。
public double getLaunchLatitude() {
return launchLatitude;
}
// 设置发射纬度。该方法将给定的纬度值限制在-90到90之间并检查是否与当前纬度相等。如果相等则不进行任何操作。
// 最后触发change事件。
public void setLaunchLatitude(double launchLatitude) {
launchLatitude = MathUtil.clamp(launchLatitude, -90, 90);
if (MathUtil.equals(this.launchLatitude, launchLatitude))
@ -276,14 +228,11 @@ public class SimulationOptions implements ChangeSource, Cloneable {
this.launchLatitude = launchLatitude;
fireChangeEvent();
}
// 获取发射经度。
public double getLaunchLongitude() {
return launchLongitude;
}
// 设置发射经度。该方法将给定的经度值限制在-180到180之间并检查是否与当前经度相等。如果相等则不进行任何操作。
// 最后触发change事件。
public void setLaunchLongitude(double launchLongitude) {
launchLongitude = MathUtil.clamp(launchLongitude, -180, 180);
if (MathUtil.equals(this.launchLongitude, launchLongitude))
@ -292,14 +241,11 @@ public class SimulationOptions implements ChangeSource, Cloneable {
fireChangeEvent();
}
// 获取地理计算策略。
public GeodeticComputationStrategy getGeodeticComputation() {
return geodeticComputation;
}
// 设置地理计算策略。如果新的策略与当前策略相等则不进行任何操作。如果新策略为null则抛出IllegalArgumentException异常。
// 最后触发change事件。
public void setGeodeticComputation(GeodeticComputationStrategy geodeticComputation) {
if (this.geodeticComputation == geodeticComputation)
return;
@ -310,14 +256,11 @@ public class SimulationOptions implements ChangeSource, Cloneable {
fireChangeEvent();
}
// 获取是否使用国际标准大气模型ISA作为大气模型。返回一个布尔值表示当前是否使用ISA模型。
public boolean isISAAtmosphere() {
return useISA;
}
// 设置是否使用ISA模型作为大气模型。如果新的值与当前值相等则不进行任何操作。最后触发change事件。
public void setISAAtmosphere(boolean isa) {
if (isa == useISA)
return;
@ -325,15 +268,13 @@ public class SimulationOptions implements ChangeSource, Cloneable {
fireChangeEvent();
}
// 获取发射温度。
public double getLaunchTemperature() {
return launchTemperature;
}
// 设置发射温度。如果新的温度与当前温度相等则不进行任何操作。最后触发change事件。
public void setLaunchTemperature(double launchTemperature) {
if (MathUtil.equals(this.launchTemperature, launchTemperature))
return;
@ -342,15 +283,13 @@ public class SimulationOptions implements ChangeSource, Cloneable {
}
// 获取发射压力。
public double getLaunchPressure() {
return launchPressure;
}
// 设置发射压力。如果新的压力与当前压力相等则不进行任何操作。最后触发change事件。
public void setLaunchPressure(double launchPressure) {
if (MathUtil.equals(this.launchPressure, launchPressure))
return;
@ -365,8 +304,6 @@ public class SimulationOptions implements ChangeSource, Cloneable {
*
* @return an AtmosphericModel object.
*/
// 根据发射条件返回对应的大气模型。如果使用ISA模型则返回ISA_ATMOSPHERIC_MODEL
// 否则返回一个基于发射高度、发射温度和发射压力的ExtendedISAModel对象。
private AtmosphericModel getAtmosphericModel() {
if (useISA) {
return ISA_ATMOSPHERIC_MODEL;
@ -374,27 +311,22 @@ public class SimulationOptions implements ChangeSource, Cloneable {
return new ExtendedISAModel(getLaunchAltitude(), launchTemperature, launchPressure);
}
// 获取时间步长。
public double getTimeStep() {
return timeStep;
}
// 设置时间步长。如果新的步长与当前步长相等则不进行任何操作。最后触发change事件。
public void setTimeStep(double timeStep) {
if (MathUtil.equals(this.timeStep, timeStep))
return;
this.timeStep = timeStep;
fireChangeEvent();
}
// 获取最大步长角度。
public double getMaximumStepAngle() {
return maximumAngle;
}
// 设置最大步长角度。该方法会将给定的角度值限制在1°到20°之间并检查是否与当前角度相等。如果相等则不进行任何操作。
// 最后触发change事件。
public void setMaximumStepAngle(double maximumAngle) {
maximumAngle = MathUtil.clamp(maximumAngle, 1 * Math.PI / 180, 20 * Math.PI / 180);
if (MathUtil.equals(this.maximumAngle, maximumAngle))
@ -404,13 +336,13 @@ public class SimulationOptions implements ChangeSource, Cloneable {
}
// 获取是否计算额外的数据。返回一个布尔值,表示当前是否计算额外的数据。
public boolean getCalculateExtras() {
return calculateExtras;
}
// 设置是否计算额外的数据。如果新的值与当前值相等则不进行任何操作。最后触发change事件。
public void setCalculateExtras(boolean calculateExtras) {
if (this.calculateExtras == calculateExtras)
return;
@ -419,13 +351,11 @@ public class SimulationOptions implements ChangeSource, Cloneable {
}
// 获取随机种子值。
public int getRandomSeed() {
return randomSeed;
}
// 设置随机种子值。如果新的值与当前值相等,则不进行任何操作。
// 该方法不会触发change事件因为更改种子值可能会影响模拟结果的有效性。
public void setRandomSeed(int randomSeed) {
if (this.randomSeed == randomSeed) {
return;
@ -442,15 +372,13 @@ public class SimulationOptions implements ChangeSource, Cloneable {
/**
* Randomize the random seed value.
*/
// 随机生成一个新的种子值。
public void randomizeSeed() {
this.randomSeed = new Random().nextInt();
// fireChangeEvent();
}
// 克隆SimulationOptions对象。返回一个新的SimulationOptions对象它的所有成员变量与原始对象相同。
@Override
public SimulationOptions clone() {
try {
@ -462,8 +390,7 @@ public class SimulationOptions implements ChangeSource, Cloneable {
}
}
// 从另一个SimulationOptions对象中复制所有成员变量的值。该方法将当前对象的所有成员变量设置为源对象的对应值并触发change事件。
public void copyFrom(SimulationOptions src) {
this.launchAltitude = src.launchAltitude;
@ -484,9 +411,7 @@ public class SimulationOptions implements ChangeSource, Cloneable {
fireChangeEvent();
}
// 方法的作用是从另一个SimulationOptions对象中复制条件launchAltitude、launchLatitude等的值。
// 如果任何一个“重要”参数用户指定的参数发生了实际变化那么就会触发change事件。
public void copyConditionsFrom(SimulationOptions src) {
// Be a little smart about triggering the change event.
// only do it if one of the "important" (user specified) parameters has really changed.
@ -562,8 +487,6 @@ public class SimulationOptions implements ChangeSource, Cloneable {
* Compares whether the two simulation conditions are equal. The two are considered
* equal if the rocket, motor id and all variables are equal.
*/
// 用于比较两个SimulationOptions对象是否相等。如果这两个对象的火箭、发动机ID和所有变量都相等则认为它们是相等的。
// 如果有任何一个成员变量不相等则返回false否则返回true。
@Override
public boolean equals(Object other) {
if (!(other instanceof SimulationOptions))
@ -592,22 +515,19 @@ public class SimulationOptions implements ChangeSource, Cloneable {
public int hashCode() {
return 0;
}
// 用于向监听器列表中添加新的StateChangeListener监听器。
@Override
public void addChangeListener(StateChangeListener listener) {
listeners.add(listener);
}
// 用于从监听器列表中删除指定的StateChangeListener监听器。
@Override
public void removeChangeListener(StateChangeListener listener) {
listeners.remove(listener);
}
private final EventObject event = new EventObject(this);
// 用于触发状态更改事件。将通知所有注册的监听器,当前对象的状态已发生更改。
private void fireChangeEvent() {
// Copy the list before iterating to prevent concurrent modification exceptions.
@ -619,8 +539,7 @@ public class SimulationOptions implements ChangeSource, Cloneable {
}
}
// 该方法的作用是将SimulationOptions对象转换为SimulationConditions对象。
// TODO: HIGH: Clean up
public SimulationConditions toSimulationConditions() {
SimulationConditions conditions = new SimulationConditions();

@ -34,101 +34,65 @@ import net.sf.openrocket.util.WorldCoordinate;
public class SimulationStatus implements Monitorable {
// SimulationConditions对象包含了模拟条件信息。
private SimulationConditions simulationConditions;
// FlightConfiguration对象包含了飞行配置信息。
private FlightConfiguration configuration;
// FlightDataBranch对象包含了飞行数据信息。
private FlightDataBranch flightData;
// 表示当前时间。
private double time;
// 表示上一步的时间步长。
private double previousTimeStep;
// 表示火箭在局部坐标系中的位置。
private Coordinate position;
// 表示火箭在全局坐标系中的位置。
private WorldCoordinate worldPosition;
// 表示火箭在局部坐标系中的速度。
private Coordinate velocity;
// 表示火箭在局部坐标系中的加速度。
private Coordinate acceleration;
// 表示火箭的姿态。
private Quaternion orientation;
// 表示火箭在局部坐标系中的旋转速度。
private Coordinate rotationVelocity;
// 表示有效发射杆长度。
private double effectiveLaunchRodLength;
// Set of all motors
// 表示所有电机的状态。
// Set of all motors
private final List<MotorClusterState> motorStateList = new ArrayList<MotorClusterState>();
/** Nanosecond time when the simulation was started. */
// 表示模拟开始时的系统时间。
private long simulationStartWallTime = Long.MIN_VALUE;
/** Set to true when a motor has ignited. */
// 表示电机是否点火。
private boolean motorIgnited = false;
/** Set to true when the rocket has risen from the ground. */
// 表示火箭是否离地。
private boolean liftoff = false;
/** Set to true when the launch rod has been cleared. */
// 表示发射杆是否被清除。
private boolean launchRodCleared = false;
/** Set to true when apogee has been detected. */
// 表示是否达到顶点。
private boolean apogeeReached = false;
/** Set to true to indicate the rocket is tumbling. */
// 表示火箭是否翻滚。
private boolean tumbling = false;
/** Set to true to indicate rocket has landed */
// 表示火箭是否着陆。
private boolean landed = false;
/** Contains a list of deployed recovery devices. */
// MonitorableSet<RecoveryDevice>对象,表示所有已经部署的恢复设备。
private final MonitorableSet<RecoveryDevice> deployedRecoveryDevices = new MonitorableSet<RecoveryDevice>();
/** The flight event queue */
// 表示飞行事件队列。
private final EventQueue eventQueue = new EventQueue();
// 表示警告信息集合。
private WarningSet warnings;
/** Available for special purposes by the listeners. */
// Map<String, Object>对象,表示额外的数据信息。
private final Map<String, Object> extraData = new HashMap<String, Object>();
// 表示最大高度。
double maxAlt = Double.NEGATIVE_INFINITY;
// 表示达到最大高度时的时间。
double maxAltTime = 0;
// 表示模拟ID。
private int modID = 0;
// 表示模拟ID增加值。
private int modIDadd = 0;
public SimulationStatus(FlightConfiguration configuration, SimulationConditions simulationConditions) {
@ -201,11 +165,7 @@ public class SimulationStatus implements Monitorable {
* of SimulationStatus to another, or when simulating multiple stages.
* When used for simulating multiple stages, a new FlightDataBranch object
* needs to be associated with the new object.
*
* SimulationStatus deep copy
* deep cloneflight data objectshallow copy
* WarningSet WarningSet
*
*
* @param orig the object from which to copy
*/
public SimulationStatus(SimulationStatus orig) {
@ -250,33 +210,28 @@ public class SimulationStatus implements Monitorable {
this.modID = orig.modID;
this.modIDadd = orig.modIDadd;
}
// 设置当前模拟时间并将模拟ID增加1。
public void setSimulationTime(double time) {
this.time = time;
this.modID++;
}
// 获取当前模拟时间。
public double getSimulationTime() {
return time;
}
// 设置飞行配置信息并将模拟ID增加1。如果之前已经有配置信息则将其模拟ID增加到modIDadd中。
public void setConfiguration(FlightConfiguration configuration) {
if (this.configuration != null)
this.modIDadd += this.configuration.getModID();
this.modID++;
this.configuration = configuration;
}
// 获取所有电机状态的集合。
public Collection<MotorClusterState> getMotors() {
return motorStateList;
}
// 获取所有激活电机状态的集合。
public Collection<MotorClusterState> getActiveMotors() {
List<MotorClusterState> activeList = new ArrayList<MotorClusterState>();
for( MotorClusterState state: this.motorStateList ){
@ -287,18 +242,15 @@ public class SimulationStatus implements Monitorable {
return activeList;
}
// 获取飞行配置信息。
public FlightConfiguration getConfiguration() {
return configuration;
}
// 获取飞行配置信息。
public FlightConfiguration getFlightConfiguration() {
return configuration;
}
// 设置飞行数据信息并将模拟ID增加1。如果之前已经有飞行数据信息则将其模拟ID增加到modIDadd中。
public void setFlightData(FlightDataBranch flightData) {
if (this.flightData != null)
this.modIDadd += this.flightData.getModID();
@ -306,233 +258,195 @@ public class SimulationStatus implements Monitorable {
this.flightData = flightData;
}
// 获取飞行数据信息。
public FlightDataBranch getFlightData() {
return flightData;
}
// 获取上一步的时间步长。
public double getPreviousTimeStep() {
return previousTimeStep;
}
// 设置上一步的时间步长并将模拟ID增加1。
public void setPreviousTimeStep(double previousTimeStep) {
this.previousTimeStep = previousTimeStep;
this.modID++;
}
// 设置火箭在局部坐标系中的位置并将模拟ID增加1。
public void setRocketPosition(Coordinate position) {
this.position = position;
this.modID++;
}
// 获取火箭在局部坐标系中的位置。
public Coordinate getRocketPosition() {
return position;
}
// 设置火箭在全局坐标系中的位置并将模拟ID增加1。
public void setRocketWorldPosition(WorldCoordinate wc) {
this.worldPosition = wc;
this.modID++;
}
// 获取火箭在全局坐标系中的位置。
public WorldCoordinate getRocketWorldPosition() {
return worldPosition;
}
// 设置火箭在局部坐标系中的速度并将模拟ID增加1。
public void setRocketVelocity(Coordinate velocity) {
this.velocity = velocity;
this.modID++;
}
// 获取火箭在局部坐标系中的速度。
public Coordinate getRocketVelocity() {
return velocity;
}
// 设置火箭在局部坐标系中的加速度并将模拟ID增加1。
public void setRocketAcceleration(Coordinate acceleration) {
this.acceleration = acceleration;
this.modID++;
}
// 获取火箭在局部坐标系中的加速度。
public Coordinate getRocketAcceleration() {
return acceleration;
}
// 将燃尽的电机从正常电机列表中移除并添加到已使用电机列表中。
public boolean moveBurntOutMotor( final MotorConfigurationId motor) {
// get motor from normal list
// remove motor from 'normal' list
// add to spent list
return false;
}
// 获取火箭在全局坐标系中的方向四元数。
public Quaternion getRocketOrientationQuaternion() {
return orientation;
}
// 设置火箭在全局坐标系中的方向四元数并将模拟ID增加1。
public void setRocketOrientationQuaternion(Quaternion orientation) {
this.orientation = orientation;
this.modID++;
}
// 获取火箭在局部坐标系中的旋转速度。
public Coordinate getRocketRotationVelocity() {
return rotationVelocity;
}
// 设置火箭在局部坐标系中的旋转速度。
public void setRocketRotationVelocity(Coordinate rotation) {
this.rotationVelocity = rotation;
}
// 设置有效发射架长度并将模拟ID增加1。
public void setEffectiveLaunchRodLength(double effectiveLaunchRodLength) {
this.effectiveLaunchRodLength = effectiveLaunchRodLength;
this.modID++;
}
// 获取有效发射架长度。
public double getEffectiveLaunchRodLength() {
return effectiveLaunchRodLength;
}
// 设置模拟开始时间并将模拟ID增加1。
public void setSimulationStartWallTime(long simulationStartWallTime) {
this.simulationStartWallTime = simulationStartWallTime;
this.modID++;
}
// 获取模拟开始时间。
public long getSimulationStartWallTime() {
return simulationStartWallTime;
}
// 设置电机是否点火并将模拟ID增加1。
public void setMotorIgnited(boolean motorIgnited) {
this.motorIgnited = motorIgnited;
this.modID++;
}
// 获取电机是否点火。
public boolean isMotorIgnited() {
return motorIgnited;
}
// 设置火箭是否起飞并将模拟ID增加1。
public void setLiftoff(boolean liftoff) {
this.liftoff = liftoff;
this.modID++;
}
// 获取火箭是否起飞。
public boolean isLiftoff() {
return liftoff;
}
// 设置发射架是否清空并将模拟ID增加1。
public void setLaunchRodCleared(boolean launchRod) {
this.launchRodCleared = launchRod;
this.modID++;
}
// 获取发射架是否清空。
public boolean isLaunchRodCleared() {
return launchRodCleared;
}
// 设置是否到达顶点并将模拟ID增加1。
public void setApogeeReached(boolean apogeeReached) {
this.apogeeReached = apogeeReached;
this.modID++;
}
// 获取火箭是否到达顶点。
public boolean isApogeeReached() {
return apogeeReached;
}
// 设置火箭是否在翻滚并将模拟ID增加1。
public void setTumbling(boolean tumbling) {
this.tumbling = tumbling;
this.modID++;
}
// 获取火箭是否在翻滚。
public boolean isTumbling() {
return tumbling;
}
// 设置火箭是否着陆并将模拟ID增加1。
public void setLanded(boolean landed) {
this.landed = landed;
this.modID++;
}
// 获取火箭是否着陆。
public boolean isLanded() {
return landed;
}
// 获取火箭的最大高度。
public double getMaxAlt() {
return maxAlt;
}
// 设置火箭的最大高度并将模拟ID增加1。
public void setMaxAlt(double maxAlt) {
this.maxAlt = maxAlt;
this.modID++;
}
// 获取火箭达到最大高度的时间。
public double getMaxAltTime() {
return maxAltTime;
}
// 设置火箭达到最大高度的时间并将模拟ID增加1。
public void setMaxAltTime(double maxAltTime) {
this.maxAltTime = maxAltTime;
this.modID++;
}
// 获取已展开的救援设备集合。
public Set<RecoveryDevice> getDeployedRecoveryDevices() {
return deployedRecoveryDevices;
}
// 设置警告信息并将模拟ID增加1。
public void setWarnings(WarningSet warnings) {
if (this.warnings != null)
this.modIDadd += this.warnings.getModID();
@ -540,28 +454,24 @@ public class SimulationStatus implements Monitorable {
this.warnings = warnings;
}
// 获取警告信息。
public WarningSet getWarnings() {
return warnings;
}
// 获取事件队列。
public EventQueue getEventQueue() {
return eventQueue;
}
// 设置模拟条件并将模拟ID增加1。
public void setSimulationConditions(SimulationConditions simulationConditions) {
if (this.simulationConditions != null)
this.modIDadd += this.simulationConditions.getModID();
this.modID++;
this.simulationConditions = simulationConditions;
}
// 获取模拟条件。
public SimulationConditions getSimulationConditions() {
return simulationConditions;
}
@ -573,7 +483,6 @@ public class SimulationStatus implements Monitorable {
* @param key the data key
* @param value the value to store
*/
// 存储由模拟监听器可用的额外数据。
public void putExtraData(String key, Object value) {
extraData.put(key, value);
}
@ -585,7 +494,6 @@ public class SimulationStatus implements Monitorable {
* @param key the data key to retrieve
* @return the data, or <code>null</code> if nothing has been set for the key
*/
// 检索由模拟监听器存储的额外数据。该数据映射最初为空。可以使用putExtraDataStringObject存储数据。
public Object getExtraData(String key) {
return extraData.get(key);
}
@ -598,7 +506,6 @@ public class SimulationStatus implements Monitorable {
* copies of this object used during step computation.
*
*/
// 返回一个当前对象的副本。
@Override
public SimulationStatus clone() {
try {
@ -608,16 +515,14 @@ public class SimulationStatus implements Monitorable {
throw new BugException("CloneNotSupportedException?!?", e);
}
}
// 获取模拟状态对象的修改标识符modID
@Override
public int getModID() {
return (modID + modIDadd + simulationConditions.getModID() + configuration.getModID() +
flightData.getModID() + deployedRecoveryDevices.getModID() +
eventQueue.getModID() + warnings.getModID());
}
// 将事件队列中的事件转换为调试信息的字符串形式。
public String toEventDebug(){
final StringBuilder buf = new StringBuilder();
for ( FlightEvent event : this.eventQueue){
@ -632,8 +537,7 @@ public class SimulationStatus implements Monitorable {
}
return buf.toString();
}
// 将火箭的发动机状态转换为调试信息的字符串形式。
public String toMotorsDebug(){
final StringBuilder buf = new StringBuilder("MotorState list:\n");
for ( MotorClusterState state : this.motorStateList){
@ -641,8 +545,7 @@ public class SimulationStatus implements Monitorable {
}
return buf.toString();
}
// 填充发动机状态列表。
private void populateMotors(){
motorStateList.clear();
for( MotorConfiguration motorConfig : this.configuration.getAllMotors() ) {

@ -12,11 +12,9 @@ import com.google.inject.Injector;
/**
* A class that provides singleton instances / beans for other classes to utilize.
*
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
//提供单例实例/bean供其他类使用。它包含了一些静态方法和属性用于获取全局唯一的实例或对象。
public final class Application {
private static ExceptionHandler exceptionHandler;

@ -1,12 +1,12 @@
package net.sf.openrocket.startup;
public interface ExceptionHandler {
public void handleErrorCondition(String message);
public void handleErrorCondition(String message, Throwable exception);
public void handleErrorCondition(final Throwable exception);
public void uncaughtException(final Thread thread, final Throwable throwable);
}
package net.sf.openrocket.startup;
public interface ExceptionHandler {
public void handleErrorCondition(String message);
public void handleErrorCondition(String message, Throwable exception);
public void handleErrorCondition(final Throwable exception);
public void uncaughtException(final Thread thread, final Throwable throwable);
}

File diff suppressed because it is too large Load Diff

@ -1,122 +1,122 @@
package net.sf.openrocket.thrustcurve;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
public abstract class Base64Decoder {
private static final String BASE64_CHARS =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
private static final char PAD_CHAR = '=';
private final static short[] _charToBits = new short[128];
static {
for (int i = 0; i < _charToBits.length; i++)
_charToBits[i] = -1;
for (int i = 0; i < BASE64_CHARS.length(); i++)
_charToBits[BASE64_CHARS.charAt(i)] = (byte) i;
_charToBits[PAD_CHAR] = 0;
}
/**
* Decode the specified Base64 string and write binary data
* to the given stream.
* @param str Base64 encoded string
* @param w output stream
*/
public static String decodeData(String str) throws IOException
{
StringReader r;
int c1;
if (str == null || str.length() < 1)
return null;
r = new StringReader(str);
StringWriter w = new StringWriter();
// spin through the input string
c1 = readToNonSpace(r);
while (c1 > 0)
{
int c2, c3, c4;
int p1, p2, p3, p4;
int pad, n;
pad = 0;
c2 = readToNonSpace(r);
c3 = readToNonSpace(r);
c4 = readToNonSpace(r);
if (c4 < 0)
throw new IllegalArgumentException("Encoded string ends prematurely.");
p1 = charToBits(c1);
p2 = charToBits(c2);
if (c3 == PAD_CHAR)
{
p3 = 0;
pad++;
}
else
p3 = charToBits(c3);
if (c4 == PAD_CHAR)
{
p4 = 0;
pad++;
}
else
p4 = charToBits(c4);
if (p1 < 0 || p2 < 0 || p3 < 0 || p4 < 0)
throw new IllegalArgumentException("Encoded string contains invalid characters.");
n = (p1 << 18) | (p2 << 12) | (p3 << 6) | p4;
w.write((byte) ((n & 0xFF0000) >> 16));
if (pad < 2)
w.write((byte) ((n & 0x00FF00) >> 8));
if (pad < 1)
w.write((byte) (n & 0x0000FF));
c1 = readToNonSpace(r);
if (c1 > 0 && pad > 0)
throw new IllegalArgumentException("Extra characters found after padding.");
}
return w.toString();
}
private static int readToNonSpace(Reader r)
throws IOException
{
int c;
c = r.read();
while (c >= 0 && Character.isWhitespace(c))
c = r.read();
return c;
}
private static int charToBits(int c)
{
// use it to look up the value
if (c < 0 || c >= _charToBits.length)
return -1;
else
return _charToBits[c];
}
}
package net.sf.openrocket.thrustcurve;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
public abstract class Base64Decoder {
private static final String BASE64_CHARS =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
private static final char PAD_CHAR = '=';
private final static short[] _charToBits = new short[128];
static {
for (int i = 0; i < _charToBits.length; i++)
_charToBits[i] = -1;
for (int i = 0; i < BASE64_CHARS.length(); i++)
_charToBits[BASE64_CHARS.charAt(i)] = (byte) i;
_charToBits[PAD_CHAR] = 0;
}
/**
* Decode the specified Base64 string and write binary data
* to the given stream.
* @param str Base64 encoded string
* @param w output stream
*/
public static String decodeData(String str) throws IOException
{
StringReader r;
int c1;
if (str == null || str.length() < 1)
return null;
r = new StringReader(str);
StringWriter w = new StringWriter();
// spin through the input string
c1 = readToNonSpace(r);
while (c1 > 0)
{
int c2, c3, c4;
int p1, p2, p3, p4;
int pad, n;
pad = 0;
c2 = readToNonSpace(r);
c3 = readToNonSpace(r);
c4 = readToNonSpace(r);
if (c4 < 0)
throw new IllegalArgumentException("Encoded string ends prematurely.");
p1 = charToBits(c1);
p2 = charToBits(c2);
if (c3 == PAD_CHAR)
{
p3 = 0;
pad++;
}
else
p3 = charToBits(c3);
if (c4 == PAD_CHAR)
{
p4 = 0;
pad++;
}
else
p4 = charToBits(c4);
if (p1 < 0 || p2 < 0 || p3 < 0 || p4 < 0)
throw new IllegalArgumentException("Encoded string contains invalid characters.");
n = (p1 << 18) | (p2 << 12) | (p3 << 6) | p4;
w.write((byte) ((n & 0xFF0000) >> 16));
if (pad < 2)
w.write((byte) ((n & 0x00FF00) >> 8));
if (pad < 1)
w.write((byte) (n & 0x0000FF));
c1 = readToNonSpace(r);
if (c1 > 0 && pad > 0)
throw new IllegalArgumentException("Extra characters found after padding.");
}
return w.toString();
}
private static int readToNonSpace(Reader r)
throws IOException
{
int c;
c = r.read();
while (c >= 0 && Character.isWhitespace(c))
c = r.read();
return c;
}
private static int charToBits(int c)
{
// use it to look up the value
if (c < 0 || c >= _charToBits.length)
return -1;
else
return _charToBits[c];
}
}

@ -1,43 +1,43 @@
package net.sf.openrocket.thrustcurve;
import java.util.ArrayList;
class DownloadRequest {
private final ArrayList<Integer> motorIds = new ArrayList<Integer>();
private String format = null;
public void add(Integer motorId) {
this.motorIds.add(motorId);
}
public void setFormat(String format) {
this.format = format;
}
@Override
public String toString() {
StringBuilder w = new StringBuilder();
w.append("<?xml version=\"1.0\" encoding=\"ascii\"?>\n");
w.append("<download-request\n");
w.append(" xmlns=\"http://www.thrustcurve.org/2008/DownloadRequest\"\n");
w.append(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
w.append(" xsi:schemaLocation=\"http://www.thrustcurve.org/2008/DownloadRequest http://www.thrustcurve.org/2008/download-request.xsd\">\n");
if (format != null) {
w.append(" <format>").append(format).append("</format>\n");
}
w.append(" <motor-ids>\n");
for (Integer i : motorIds) {
w.append(" <id>").append(i).append("</id>\n");
}
w.append(" </motor-ids>\n");
w.append("</download-request>\n");
return w.toString();
}
}
package net.sf.openrocket.thrustcurve;
import java.util.ArrayList;
class DownloadRequest {
private final ArrayList<Integer> motorIds = new ArrayList<Integer>();
private String format = null;
public void add(Integer motorId) {
this.motorIds.add(motorId);
}
public void setFormat(String format) {
this.format = format;
}
@Override
public String toString() {
StringBuilder w = new StringBuilder();
w.append("<?xml version=\"1.0\" encoding=\"ascii\"?>\n");
w.append("<download-request\n");
w.append(" xmlns=\"http://www.thrustcurve.org/2008/DownloadRequest\"\n");
w.append(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
w.append(" xsi:schemaLocation=\"http://www.thrustcurve.org/2008/DownloadRequest http://www.thrustcurve.org/2008/download-request.xsd\">\n");
if (format != null) {
w.append(" <format>").append(format).append("</format>\n");
}
w.append(" <motor-ids>\n");
for (Integer i : motorIds) {
w.append(" <id>").append(i).append("</id>\n");
}
w.append(" </motor-ids>\n");
w.append("</download-request>\n");
return w.toString();
}
}

@ -1,41 +1,41 @@
package net.sf.openrocket.thrustcurve;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DownloadResponse {
private final Map<Integer,List<MotorBurnFile>> data = new HashMap<Integer,List<MotorBurnFile>>();
private String error = null;
public void add( MotorBurnFile mbd ) {
List<MotorBurnFile> currentData = data.get(mbd.getMotorId());
if ( currentData == null ) {
currentData = new ArrayList<MotorBurnFile>();
data.put(mbd.getMotorId(), currentData);
}
currentData.add(mbd);
}
public List<MotorBurnFile> getData(Integer motor_id) {
return data.get(motor_id);
}
public void setError(String error) {
this.error = error;
}
public String getError() {
return error;
}
@Override
public String toString() {
return "DownloadResponse [error=" + error + ", data=" + data + "]";
}
}
package net.sf.openrocket.thrustcurve;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DownloadResponse {
private final Map<Integer,List<MotorBurnFile>> data = new HashMap<Integer,List<MotorBurnFile>>();
private String error = null;
public void add( MotorBurnFile mbd ) {
List<MotorBurnFile> currentData = data.get(mbd.getMotorId());
if ( currentData == null ) {
currentData = new ArrayList<MotorBurnFile>();
data.put(mbd.getMotorId(), currentData);
}
currentData.add(mbd);
}
public List<MotorBurnFile> getData(Integer motor_id) {
return data.get(motor_id);
}
public void setError(String error) {
this.error = error;
}
public String getError() {
return error;
}
@Override
public String toString() {
return "DownloadResponse [error=" + error + ", data=" + data + "]";
}
}

@ -1,77 +1,77 @@
package net.sf.openrocket.thrustcurve;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.SimpleSAX;
public class DownloadResponseParser implements ElementHandler {
private static final String thrustcurveURI = "http://www.thrustcurve.org/2009/DownloadResponse";
private static final String root_tag = "download-response";
private static final String results_tag = "results";
private static final String result_tag = "result";
private static final String motor_id_tag = "motor-id";
private static final String simfile_id_tag = "simfile-id";
private static final String format_tag = "format";
private static final String source_tag = "source";
private static final String license_tag = "license";
private static final String data_tag = "data";
private static final String error_tag = "error";
private final DownloadResponse response = new DownloadResponse();
private MotorBurnFile motorBurnFile;
private DownloadResponseParser() {
}
public static DownloadResponse parse(InputStream in) throws IOException, SAXException {
DownloadResponseParser handler = new DownloadResponseParser();
WarningSet warnings = new WarningSet();
SimpleSAX.readXML(new InputSource(in), handler, warnings);
return handler.response;
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) throws SAXException {
if (result_tag.equals(element)) {
motorBurnFile = new MotorBurnFile();
}
return this;
}
@Override
public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
if (result_tag.equals(element)) {
response.add(motorBurnFile);
} else if (motor_id_tag.equals(element)) {
motorBurnFile.setMotorId(Integer.parseInt(content));
} else if (simfile_id_tag.equals(element)) {
motorBurnFile.setSimfileId(Integer.parseInt(content));
} else if (format_tag.equals(element)) {
motorBurnFile.setFiletype(content);
} else if (data_tag.equals(element)) {
try {
motorBurnFile.decodeFile(content);
} catch (IOException e) {
throw new SAXException(e);
}
}
}
@Override
public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
}
}
package net.sf.openrocket.thrustcurve;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.SimpleSAX;
public class DownloadResponseParser implements ElementHandler {
private static final String thrustcurveURI = "http://www.thrustcurve.org/2009/DownloadResponse";
private static final String root_tag = "download-response";
private static final String results_tag = "results";
private static final String result_tag = "result";
private static final String motor_id_tag = "motor-id";
private static final String simfile_id_tag = "simfile-id";
private static final String format_tag = "format";
private static final String source_tag = "source";
private static final String license_tag = "license";
private static final String data_tag = "data";
private static final String error_tag = "error";
private final DownloadResponse response = new DownloadResponse();
private MotorBurnFile motorBurnFile;
private DownloadResponseParser() {
}
public static DownloadResponse parse(InputStream in) throws IOException, SAXException {
DownloadResponseParser handler = new DownloadResponseParser();
WarningSet warnings = new WarningSet();
SimpleSAX.readXML(new InputSource(in), handler, warnings);
return handler.response;
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) throws SAXException {
if (result_tag.equals(element)) {
motorBurnFile = new MotorBurnFile();
}
return this;
}
@Override
public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
if (result_tag.equals(element)) {
response.add(motorBurnFile);
} else if (motor_id_tag.equals(element)) {
motorBurnFile.setMotorId(Integer.parseInt(content));
} else if (simfile_id_tag.equals(element)) {
motorBurnFile.setSimfileId(Integer.parseInt(content));
} else if (format_tag.equals(element)) {
motorBurnFile.setFiletype(content);
} else if (data_tag.equals(element)) {
try {
motorBurnFile.decodeFile(content);
} catch (IOException e) {
throw new SAXException(e);
}
}
}
@Override
public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
}
}

@ -1,108 +1,108 @@
package net.sf.openrocket.thrustcurve;
import java.io.IOException;
import java.io.StringReader;
import java.util.List;
import net.sf.openrocket.file.motor.RASPMotorLoader;
import net.sf.openrocket.file.motor.RockSimMotorLoader;
import net.sf.openrocket.motor.ThrustCurveMotor;
public class MotorBurnFile {
private Integer motorId;
private Integer simfileId;
private String filetype;
private ThrustCurveMotor.Builder thrustCurveMotor;
private String data;
public void init() {
this.motorId = null;
this.filetype = null;
this.thrustCurveMotor = null;
}
@Override
public MotorBurnFile clone() {
MotorBurnFile clone = new MotorBurnFile();
clone.motorId = this.motorId;
clone.filetype = this.filetype;
clone.thrustCurveMotor = this.thrustCurveMotor;
return clone;
}
public void decodeFile(String _data) throws IOException {
_data = Base64Decoder.decodeData(_data);
data = _data;
try {
if (SupportedFileTypes.RASP_FORMAT.equals(filetype)) {
RASPMotorLoader loader = new RASPMotorLoader();
List<ThrustCurveMotor.Builder> motors = loader.load(new StringReader(data), "download");
this.thrustCurveMotor = motors.get(0);
} else if (SupportedFileTypes.ROCKSIM_FORMAT.equals(filetype)) {
RockSimMotorLoader loader = new RockSimMotorLoader();
List<ThrustCurveMotor.Builder> motors = loader.load(new StringReader(data), "download");
this.thrustCurveMotor = motors.get(0);
}
} catch (IOException ex) {
this.thrustCurveMotor = null;
}
}
/**
* @return the motor id
*/
public Integer getMotorId() {
return motorId;
}
/**
* @param motorId the motor id to set
*/
public void setMotorId(Integer motorId) {
this.motorId = motorId;
}
/**
* @return the simfile id
*/
public Integer getSimfileId() {
return simfileId;
}
/**
* @param simfileId the simfileId to set
*/
public void setSimfileId(Integer simfileId) {
this.simfileId = simfileId;
}
/**
* @return the filetype
*/
public String getFiletype() {
return filetype;
}
/**
* @param filetype the filetype to set
*/
public void setFiletype(String filetype) {
this.filetype = filetype;
}
/**
* @return the thrustCurveMotor
*/
public ThrustCurveMotor.Builder getThrustCurveMotor() {
return thrustCurveMotor;
}
/**
* @return the file contents
*/
public String getContents() {
return data;
}
}
package net.sf.openrocket.thrustcurve;
import java.io.IOException;
import java.io.StringReader;
import java.util.List;
import net.sf.openrocket.file.motor.RASPMotorLoader;
import net.sf.openrocket.file.motor.RockSimMotorLoader;
import net.sf.openrocket.motor.ThrustCurveMotor;
public class MotorBurnFile {
private Integer motorId;
private Integer simfileId;
private String filetype;
private ThrustCurveMotor.Builder thrustCurveMotor;
private String data;
public void init() {
this.motorId = null;
this.filetype = null;
this.thrustCurveMotor = null;
}
@Override
public MotorBurnFile clone() {
MotorBurnFile clone = new MotorBurnFile();
clone.motorId = this.motorId;
clone.filetype = this.filetype;
clone.thrustCurveMotor = this.thrustCurveMotor;
return clone;
}
public void decodeFile(String _data) throws IOException {
_data = Base64Decoder.decodeData(_data);
data = _data;
try {
if (SupportedFileTypes.RASP_FORMAT.equals(filetype)) {
RASPMotorLoader loader = new RASPMotorLoader();
List<ThrustCurveMotor.Builder> motors = loader.load(new StringReader(data), "download");
this.thrustCurveMotor = motors.get(0);
} else if (SupportedFileTypes.ROCKSIM_FORMAT.equals(filetype)) {
RockSimMotorLoader loader = new RockSimMotorLoader();
List<ThrustCurveMotor.Builder> motors = loader.load(new StringReader(data), "download");
this.thrustCurveMotor = motors.get(0);
}
} catch (IOException ex) {
this.thrustCurveMotor = null;
}
}
/**
* @return the motor id
*/
public Integer getMotorId() {
return motorId;
}
/**
* @param motorId the motor id to set
*/
public void setMotorId(Integer motorId) {
this.motorId = motorId;
}
/**
* @return the simfile id
*/
public Integer getSimfileId() {
return simfileId;
}
/**
* @param simfileId the simfileId to set
*/
public void setSimfileId(Integer simfileId) {
this.simfileId = simfileId;
}
/**
* @return the filetype
*/
public String getFiletype() {
return filetype;
}
/**
* @param filetype the filetype to set
*/
public void setFiletype(String filetype) {
this.filetype = filetype;
}
/**
* @return the thrustCurveMotor
*/
public ThrustCurveMotor.Builder getThrustCurveMotor() {
return thrustCurveMotor;
}
/**
* @return the file contents
*/
public String getContents() {
return data;
}
}

@ -1,117 +1,117 @@
package net.sf.openrocket.thrustcurve;
public class SearchRequest {
private String manufacturer;
private String designation;
private String brand_name;
private String common_name;
private String impulse_class;
private Integer diameter;
/*
public enum Type {
"SU";
"reload";
"hybrid"
};
*/
private String type;
public void setManufacturer(String manufacturer) {
this.manufacturer = null;
if (manufacturer != null) {
manufacturer = manufacturer.trim();
if (!"".equals(manufacturer)) {
this.manufacturer = manufacturer;
}
}
}
public void setDesignation(String designation) {
this.designation = designation;
}
public void setBrand_name(String brand_name) {
this.brand_name = brand_name;
}
public void setCommon_name(String common_name) {
if (common_name == null) {
this.common_name = null;
return;
}
this.common_name = common_name.trim();
if ("".equals(this.common_name)) {
this.common_name = null;
}
}
public void setImpulse_class(String impulse_class) {
this.impulse_class = null;
if (impulse_class != null) {
this.impulse_class = impulse_class.trim();
if ("".equals(impulse_class)) {
this.impulse_class = null;
}
}
}
public void setDiameter(Integer diameter) {
this.diameter = diameter;
}
public void setDiameter(String diameter) {
this.diameter = null;
if (diameter == null) {
return;
}
try {
this.diameter = Integer.decode(diameter);
} catch (NumberFormatException ex) {
this.diameter = null;
}
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
StringBuilder w = new StringBuilder();
w.append("<?xml version=\"1.0\" encoding=\"ascii\"?>\n");
w.append("<search-request\n");
w.append(" xmlns=\"http://www.thrustcurve.org/2014/SearchRequest\"\n");
w.append(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
w.append(" xsi:schemaLocation=\"http://www.thrustcurve.org/2014/SearchRequest http://www.thrustcurve.org/2014/search-request.xsd\">\n");
if (manufacturer != null) {
w.append(" <manufacturer>").append(manufacturer).append("</manufacturer>\n");
}
if (designation != null) {
w.append(" <designation>").append(designation).append("</designation>\n");
}
if (brand_name != null) {
w.append(" <brand-name>").append(brand_name).append("</brand-name>\n");
}
if (common_name != null) {
w.append(" <common-name>").append(common_name).append("</common-name>\n");
}
if (impulse_class != null) {
w.append(" <impulse-class>").append(impulse_class).append("</impulse-class>\n");
}
if (diameter != null) {
w.append(" <diameter>").append(diameter).append("</diameter>\n");
}
if (type != null) {
w.append(" <type>").append(type).append("</type>\n");
}
w.append("<data-fields>*</data-fields>");
w.append("<max-results>0</max-results>");
w.append("</search-request>\n");
return w.toString();
}
}
package net.sf.openrocket.thrustcurve;
public class SearchRequest {
private String manufacturer;
private String designation;
private String brand_name;
private String common_name;
private String impulse_class;
private Integer diameter;
/*
public enum Type {
"SU";
"reload";
"hybrid"
};
*/
private String type;
public void setManufacturer(String manufacturer) {
this.manufacturer = null;
if (manufacturer != null) {
manufacturer = manufacturer.trim();
if (!"".equals(manufacturer)) {
this.manufacturer = manufacturer;
}
}
}
public void setDesignation(String designation) {
this.designation = designation;
}
public void setBrand_name(String brand_name) {
this.brand_name = brand_name;
}
public void setCommon_name(String common_name) {
if (common_name == null) {
this.common_name = null;
return;
}
this.common_name = common_name.trim();
if ("".equals(this.common_name)) {
this.common_name = null;
}
}
public void setImpulse_class(String impulse_class) {
this.impulse_class = null;
if (impulse_class != null) {
this.impulse_class = impulse_class.trim();
if ("".equals(impulse_class)) {
this.impulse_class = null;
}
}
}
public void setDiameter(Integer diameter) {
this.diameter = diameter;
}
public void setDiameter(String diameter) {
this.diameter = null;
if (diameter == null) {
return;
}
try {
this.diameter = Integer.decode(diameter);
} catch (NumberFormatException ex) {
this.diameter = null;
}
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
StringBuilder w = new StringBuilder();
w.append("<?xml version=\"1.0\" encoding=\"ascii\"?>\n");
w.append("<search-request\n");
w.append(" xmlns=\"http://www.thrustcurve.org/2014/SearchRequest\"\n");
w.append(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
w.append(" xsi:schemaLocation=\"http://www.thrustcurve.org/2014/SearchRequest http://www.thrustcurve.org/2014/search-request.xsd\">\n");
if (manufacturer != null) {
w.append(" <manufacturer>").append(manufacturer).append("</manufacturer>\n");
}
if (designation != null) {
w.append(" <designation>").append(designation).append("</designation>\n");
}
if (brand_name != null) {
w.append(" <brand-name>").append(brand_name).append("</brand-name>\n");
}
if (common_name != null) {
w.append(" <common-name>").append(common_name).append("</common-name>\n");
}
if (impulse_class != null) {
w.append(" <impulse-class>").append(impulse_class).append("</impulse-class>\n");
}
if (diameter != null) {
w.append(" <diameter>").append(diameter).append("</diameter>\n");
}
if (type != null) {
w.append(" <type>").append(type).append("</type>\n");
}
w.append("<data-fields>*</data-fields>");
w.append("<max-results>0</max-results>");
w.append("</search-request>\n");
return w.toString();
}
}

@ -1,45 +1,45 @@
package net.sf.openrocket.thrustcurve;
import java.util.ArrayList;
import java.util.List;
public class SearchResponse {
private final List<TCMotor> results = new ArrayList<TCMotor>();
private int matches;
private String error;
public List<TCMotor> getResults() {
return results;
}
void addMotor(TCMotor motor) {
results.add(motor);
}
public int getMatches() {
return matches;
}
public void setMatches(int matches) {
this.matches = matches;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
@Override
public String toString() {
return "SearchResult [results=" + results + ", matches=" + matches
+ ", error=" + error + "]";
}
}
package net.sf.openrocket.thrustcurve;
import java.util.ArrayList;
import java.util.List;
public class SearchResponse {
private final List<TCMotor> results = new ArrayList<TCMotor>();
private int matches;
private String error;
public List<TCMotor> getResults() {
return results;
}
void addMotor(TCMotor motor) {
results.add(motor);
}
public int getMatches() {
return matches;
}
public void setMatches(int matches) {
this.matches = matches;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
@Override
public String toString() {
return "SearchResult [results=" + results + ", matches=" + matches
+ ", error=" + error + "]";
}
}

@ -1,191 +1,191 @@
package net.sf.openrocket.thrustcurve;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.SimpleSAX;
public class SearchResponseParser implements ElementHandler {
private static final String thrustcurveURI = "http://www.thrustcurve.org/2008/SearchResponse";
/*
* XML Tags in SearchResult xsd
*/
private static final String root_tag = "search-response";
private static final String criteria = "criteria";
private static final String criterion = "criterion";
private static final String name = "name";
private static final String value = "value";
private static final String matches = "matches";
private static final String results = "results";
private static final String result = "result";
private static final String motor_id = "motor-id";
private static final String manufacturer = "manufacturer";
private static final String manufacturer_abbr = "manufacturer-abbrev";
private static final String designation = "designation";
private static final String brand_name = "brand-name";
private static final String common_name = "common-name";
private static final String impulse_class = "impulse-class";
private static final String diameter = "diameter";
private static final String length = "length";
private static final String type = "type";
private static final String cert_org = "cert-org";
private static final String avg_thrust_n = "avg-thrust-n";
private static final String max_thrust_n = "max-thrust-n";
private static final String tot_impulse_ns = "tot-impulse-ns";
private static final String burn_time_s = "burn-time-s";
private static final String data_files = "data-files";
private static final String info_url = "info-url";
private static final String total_weight_g = "total-weight-g";
private static final String prop_weight_g = "prop-weight-g";
private static final String delays = "delays";
private static final String case_info = "case-info";
private static final String prop_info = "prop-info";
private static final String updated_on = "updated-on";
private static final String availability = "availability";
private final SearchResponse response = new SearchResponse();
private TCMotor currentMotor;
private SearchResponseParser() {
}
public static SearchResponse parse(InputStream in) throws IOException, SAXException {
SearchResponseParser handler = new SearchResponseParser();
WarningSet warnings = new WarningSet();
SimpleSAX.readXML(new InputSource(in), handler, warnings);
return handler.response;
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) throws SAXException {
if (result.equals(element)) {
currentMotor = new TCMotor();
}
return this;
}
@Override
public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
switch (element) {
case result:
// Convert impulse class. ThrustCurve puts mmx, 1/4a and 1/2a as A.
if ("a".equalsIgnoreCase(currentMotor.getImpulse_class())) {
if (currentMotor.getCommon_name().startsWith("1/2A")) {
currentMotor.setImpulse_class("1/2A");
} else if (currentMotor.getCommon_name().startsWith("1/4A")) {
currentMotor.setImpulse_class("1/4A");
} else if (currentMotor.getCommon_name().startsWith("Micro")) {
currentMotor.setImpulse_class("1/8A");
}
}
// Convert Case Info.
if (currentMotor.getCase_info() == null
|| "single use".equalsIgnoreCase(currentMotor.getCase_info())
|| "single-use".equalsIgnoreCase(currentMotor.getCase_info())) {
currentMotor.setCase_info(currentMotor.getType() + " " + currentMotor.getDiameter() + "x" + currentMotor.getLength());
}
response.addMotor(currentMotor);
break;
case matches:
this.response.setMatches(Integer.parseInt(content));
break;
case motor_id:
currentMotor.setMotor_id(Integer.parseInt(content));
break;
case manufacturer:
currentMotor.setManufacturer(content);
break;
case manufacturer_abbr:
currentMotor.setManufacturer_abbr(content);
break;
case designation:
currentMotor.setDesignation(content);
break;
case brand_name:
currentMotor.setBrand_name(content);
break;
case common_name:
currentMotor.setCommon_name(content);
break;
case impulse_class:
currentMotor.setImpulse_class(content);
break;
case diameter:
currentMotor.setDiameter(Float.parseFloat(content));
break;
case length:
currentMotor.setLength(Float.parseFloat(content));
break;
case type:
currentMotor.setType(content);
break;
case cert_org:
currentMotor.setCert_org(content);
break;
case avg_thrust_n:
currentMotor.setAvg_thrust_n(Float.parseFloat(content));
break;
case max_thrust_n:
currentMotor.setMax_thrust_n(Float.parseFloat(content));
break;
case tot_impulse_ns:
currentMotor.setTot_impulse_ns(Float.parseFloat(content));
break;
case burn_time_s:
currentMotor.setBurn_time_s(Float.parseFloat(content));
break;
case data_files:
currentMotor.setData_files(Integer.parseInt(content));
break;
case info_url:
currentMotor.setInfo_url(content);
break;
case total_weight_g:
currentMotor.setTot_mass_g(Double.parseDouble(content));
break;
case prop_weight_g:
currentMotor.setProp_mass_g(Double.parseDouble(content));
break;
case delays:
currentMotor.setDelays(content);
break;
case case_info:
currentMotor.setCase_info(content);
break;
case prop_info:
currentMotor.setProp_info(content);
break;
case availability:
currentMotor.setAvailability(content);
break;
case updated_on:
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
try {
currentMotor.setUpdated_on(formatter.parse(content));
} catch (ParseException ignored) { }
break;
}
}
@Override
public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
}
}
package net.sf.openrocket.thrustcurve;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.SimpleSAX;
public class SearchResponseParser implements ElementHandler {
private static final String thrustcurveURI = "http://www.thrustcurve.org/2008/SearchResponse";
/*
* XML Tags in SearchResult xsd
*/
private static final String root_tag = "search-response";
private static final String criteria = "criteria";
private static final String criterion = "criterion";
private static final String name = "name";
private static final String value = "value";
private static final String matches = "matches";
private static final String results = "results";
private static final String result = "result";
private static final String motor_id = "motor-id";
private static final String manufacturer = "manufacturer";
private static final String manufacturer_abbr = "manufacturer-abbrev";
private static final String designation = "designation";
private static final String brand_name = "brand-name";
private static final String common_name = "common-name";
private static final String impulse_class = "impulse-class";
private static final String diameter = "diameter";
private static final String length = "length";
private static final String type = "type";
private static final String cert_org = "cert-org";
private static final String avg_thrust_n = "avg-thrust-n";
private static final String max_thrust_n = "max-thrust-n";
private static final String tot_impulse_ns = "tot-impulse-ns";
private static final String burn_time_s = "burn-time-s";
private static final String data_files = "data-files";
private static final String info_url = "info-url";
private static final String total_weight_g = "total-weight-g";
private static final String prop_weight_g = "prop-weight-g";
private static final String delays = "delays";
private static final String case_info = "case-info";
private static final String prop_info = "prop-info";
private static final String updated_on = "updated-on";
private static final String availability = "availability";
private final SearchResponse response = new SearchResponse();
private TCMotor currentMotor;
private SearchResponseParser() {
}
public static SearchResponse parse(InputStream in) throws IOException, SAXException {
SearchResponseParser handler = new SearchResponseParser();
WarningSet warnings = new WarningSet();
SimpleSAX.readXML(new InputSource(in), handler, warnings);
return handler.response;
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) throws SAXException {
if (result.equals(element)) {
currentMotor = new TCMotor();
}
return this;
}
@Override
public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
switch (element) {
case result:
// Convert impulse class. ThrustCurve puts mmx, 1/4a and 1/2a as A.
if ("a".equalsIgnoreCase(currentMotor.getImpulse_class())) {
if (currentMotor.getCommon_name().startsWith("1/2A")) {
currentMotor.setImpulse_class("1/2A");
} else if (currentMotor.getCommon_name().startsWith("1/4A")) {
currentMotor.setImpulse_class("1/4A");
} else if (currentMotor.getCommon_name().startsWith("Micro")) {
currentMotor.setImpulse_class("1/8A");
}
}
// Convert Case Info.
if (currentMotor.getCase_info() == null
|| "single use".equalsIgnoreCase(currentMotor.getCase_info())
|| "single-use".equalsIgnoreCase(currentMotor.getCase_info())) {
currentMotor.setCase_info(currentMotor.getType() + " " + currentMotor.getDiameter() + "x" + currentMotor.getLength());
}
response.addMotor(currentMotor);
break;
case matches:
this.response.setMatches(Integer.parseInt(content));
break;
case motor_id:
currentMotor.setMotor_id(Integer.parseInt(content));
break;
case manufacturer:
currentMotor.setManufacturer(content);
break;
case manufacturer_abbr:
currentMotor.setManufacturer_abbr(content);
break;
case designation:
currentMotor.setDesignation(content);
break;
case brand_name:
currentMotor.setBrand_name(content);
break;
case common_name:
currentMotor.setCommon_name(content);
break;
case impulse_class:
currentMotor.setImpulse_class(content);
break;
case diameter:
currentMotor.setDiameter(Float.parseFloat(content));
break;
case length:
currentMotor.setLength(Float.parseFloat(content));
break;
case type:
currentMotor.setType(content);
break;
case cert_org:
currentMotor.setCert_org(content);
break;
case avg_thrust_n:
currentMotor.setAvg_thrust_n(Float.parseFloat(content));
break;
case max_thrust_n:
currentMotor.setMax_thrust_n(Float.parseFloat(content));
break;
case tot_impulse_ns:
currentMotor.setTot_impulse_ns(Float.parseFloat(content));
break;
case burn_time_s:
currentMotor.setBurn_time_s(Float.parseFloat(content));
break;
case data_files:
currentMotor.setData_files(Integer.parseInt(content));
break;
case info_url:
currentMotor.setInfo_url(content);
break;
case total_weight_g:
currentMotor.setTot_mass_g(Double.parseDouble(content));
break;
case prop_weight_g:
currentMotor.setProp_mass_g(Double.parseDouble(content));
break;
case delays:
currentMotor.setDelays(content);
break;
case case_info:
currentMotor.setCase_info(content);
break;
case prop_info:
currentMotor.setProp_info(content);
break;
case availability:
currentMotor.setAvailability(content);
break;
case updated_on:
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
try {
currentMotor.setUpdated_on(formatter.parse(content));
} catch (ParseException ignored) { }
break;
}
}
@Override
public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
}
}

@ -1,11 +1,11 @@
package net.sf.openrocket.thrustcurve;
public abstract class SupportedFileTypes {
public final static String ROCKSIM_FORMAT = "RockSim";
public final static String RASP_FORMAT = "RASP";
public static boolean isSupportedFileType( String arg0 ) {
return (ROCKSIM_FORMAT.equals(arg0) || RASP_FORMAT.equals(arg0));
}
}
package net.sf.openrocket.thrustcurve;
public abstract class SupportedFileTypes {
public final static String ROCKSIM_FORMAT = "RockSim";
public final static String RASP_FORMAT = "RASP";
public static boolean isSupportedFileType( String arg0 ) {
return (ROCKSIM_FORMAT.equals(arg0) || RASP_FORMAT.equals(arg0));
}
}

@ -1,298 +1,298 @@
package net.sf.openrocket.thrustcurve;
import java.util.Date;
public class TCMotor implements Cloneable {
private Integer motor_id;
private String manufacturer;
private String manufacturer_abbr;
private String designation;
private String brand_name;
private String common_name;
private String impulse_class;
private Float diameter;
private Float length;
private String type;
private String cert_org;
private Float avg_thrust_n;
private Float max_thrust_n;
private Float tot_impulse_ns;
private Float burn_time_s;
private Integer data_files;
private String info_url;
private Double tot_mass_g;
private Double prop_mass_g;
private String delays;
private String case_info;
private String prop_info;
private Date updated_on;
private String availability;
public void init() {
motor_id = null;
manufacturer = null;
manufacturer_abbr = null;
designation = null;
brand_name = null;
common_name = null;
impulse_class = null;
diameter = null;
length = null;
type = null;
cert_org = null;
avg_thrust_n = null;
max_thrust_n = null;
tot_impulse_ns = null;
burn_time_s = null;
data_files = null;
info_url = null;
tot_mass_g = null;
prop_mass_g = null;
delays = null;
case_info = null;
prop_info = null;
updated_on = null;
availability = null;
}
@Override
public TCMotor clone() {
TCMotor clone = new TCMotor();
clone.motor_id = this.motor_id;
clone.manufacturer = this.manufacturer;
clone.manufacturer_abbr = this.manufacturer_abbr;
clone.designation = this.designation;
clone.brand_name = this.brand_name;
clone.common_name = this.common_name;
clone.impulse_class = this.impulse_class;
clone.diameter = this.diameter;
clone.length = this.length;
clone.type = this.type;
clone.cert_org = this.cert_org;
clone.avg_thrust_n = this.avg_thrust_n;
clone.max_thrust_n = this.max_thrust_n;
clone.tot_impulse_ns = this.tot_impulse_ns;
clone.burn_time_s = this.burn_time_s;
clone.data_files = this.data_files;
clone.info_url = this.info_url;
clone.tot_mass_g = this.tot_mass_g;
clone.prop_mass_g = this.prop_mass_g;
clone.delays = this.delays;
clone.case_info = this.case_info;
clone.prop_info = this.prop_info;
clone.updated_on = this.updated_on;
clone.availability = this.availability;
return clone;
}
public Integer getMotor_id() {
return motor_id;
}
public void setMotor_id(Integer motor_id) {
this.motor_id = motor_id;
}
public String getManufacturer() {
return manufacturer;
}
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
public String getManufacturer_abbr() {
return manufacturer_abbr;
}
public void setManufacturer_abbr(String manufacturer_abbr) {
this.manufacturer_abbr = manufacturer_abbr;
}
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
public String getBrand_name() {
return brand_name;
}
public void setBrand_name(String brand_name) {
this.brand_name = brand_name;
}
public String getCommon_name() {
return common_name;
}
public void setCommon_name(String common_name) {
this.common_name = common_name;
}
public String getImpulse_class() {
return impulse_class;
}
public void setImpulse_class(String impulse_class) {
this.impulse_class = impulse_class;
}
public Float getDiameter() {
return diameter;
}
public void setDiameter(Float diameter) {
this.diameter = diameter;
}
public Float getLength() {
return length;
}
public void setLength(Float length) {
this.length = length;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getCert_org() {
return cert_org;
}
public void setCert_org(String cert_org) {
this.cert_org = cert_org;
}
public Float getAvg_thrust_n() {
return avg_thrust_n;
}
public void setAvg_thrust_n(Float avg_thrust_n) {
this.avg_thrust_n = avg_thrust_n;
}
public Float getMax_thrust_n() {
return max_thrust_n;
}
public void setMax_thrust_n(Float max_thrust_n) {
this.max_thrust_n = max_thrust_n;
}
public Float getTot_impulse_ns() {
return tot_impulse_ns;
}
public void setTot_impulse_ns(Float tot_impulse_ns) {
this.tot_impulse_ns = tot_impulse_ns;
}
public Float getBurn_time_s() {
return burn_time_s;
}
public void setBurn_time_s(Float burn_time_s) {
this.burn_time_s = burn_time_s;
}
public Integer getData_files() {
return data_files;
}
public void setData_files(Integer data_files) {
this.data_files = data_files;
}
public String getInfo_url() {
return info_url;
}
public void setInfo_url(String info_url) {
this.info_url = info_url;
}
public Double getTot_mass_g() {
return tot_mass_g;
}
public void setTot_mass_g(Double tot_mass_g) {
this.tot_mass_g = tot_mass_g;
}
public Double getProp_mass_g() {
return prop_mass_g;
}
public void setProp_mass_g(Double prop_mass_g) {
this.prop_mass_g = prop_mass_g;
}
public String getDelays() {
return delays;
}
public void setDelays(String delays) {
this.delays = delays;
}
public String getCase_info() {
return case_info;
}
public void setCase_info(String case_info) {
this.case_info = case_info;
}
public String getProp_info() {
return prop_info;
}
public void setProp_info(String prop_info) {
this.prop_info = prop_info;
}
public Date getUpdated_on() {
return updated_on;
}
public void setUpdated_on(Date updated_on) {
this.updated_on = updated_on;
}
public String getAvailability() {
return availability;
}
public void setAvailability(String avail) {
this.availability = avail;
}
@Override
public String toString() {
return "TCMotor [motor_id=" + motor_id + ", manufacturer="
+ manufacturer + ", manufacturer_abbr=" + manufacturer_abbr
+ ", designation=" + designation + ", brand_name=" + brand_name
+ ", common_name=" + common_name + ", impulse_class="
+ impulse_class + ", diameter=" + diameter + ", length="
+ length + ", type=" + type + ", cert_org=" + cert_org
+ ", avg_thrust_n=" + avg_thrust_n + ", max_thrust_n="
+ max_thrust_n + ", tot_impulse_ns=" + tot_impulse_ns
+ ", burn_time_s=" + burn_time_s + ", data_files=" + data_files
+ ", info_url=" + info_url + ", tot_mass_g=" + tot_mass_g
+ ", prop_mass_g=" + prop_mass_g + ", delays=" + delays
+ ", case_info=" + case_info + ", prop_info=" + prop_info
+ ", updated_on=" + updated_on + ", availability=" + availability + "]";
}
}
package net.sf.openrocket.thrustcurve;
import java.util.Date;
public class TCMotor implements Cloneable {
private Integer motor_id;
private String manufacturer;
private String manufacturer_abbr;
private String designation;
private String brand_name;
private String common_name;
private String impulse_class;
private Float diameter;
private Float length;
private String type;
private String cert_org;
private Float avg_thrust_n;
private Float max_thrust_n;
private Float tot_impulse_ns;
private Float burn_time_s;
private Integer data_files;
private String info_url;
private Double tot_mass_g;
private Double prop_mass_g;
private String delays;
private String case_info;
private String prop_info;
private Date updated_on;
private String availability;
public void init() {
motor_id = null;
manufacturer = null;
manufacturer_abbr = null;
designation = null;
brand_name = null;
common_name = null;
impulse_class = null;
diameter = null;
length = null;
type = null;
cert_org = null;
avg_thrust_n = null;
max_thrust_n = null;
tot_impulse_ns = null;
burn_time_s = null;
data_files = null;
info_url = null;
tot_mass_g = null;
prop_mass_g = null;
delays = null;
case_info = null;
prop_info = null;
updated_on = null;
availability = null;
}
@Override
public TCMotor clone() {
TCMotor clone = new TCMotor();
clone.motor_id = this.motor_id;
clone.manufacturer = this.manufacturer;
clone.manufacturer_abbr = this.manufacturer_abbr;
clone.designation = this.designation;
clone.brand_name = this.brand_name;
clone.common_name = this.common_name;
clone.impulse_class = this.impulse_class;
clone.diameter = this.diameter;
clone.length = this.length;
clone.type = this.type;
clone.cert_org = this.cert_org;
clone.avg_thrust_n = this.avg_thrust_n;
clone.max_thrust_n = this.max_thrust_n;
clone.tot_impulse_ns = this.tot_impulse_ns;
clone.burn_time_s = this.burn_time_s;
clone.data_files = this.data_files;
clone.info_url = this.info_url;
clone.tot_mass_g = this.tot_mass_g;
clone.prop_mass_g = this.prop_mass_g;
clone.delays = this.delays;
clone.case_info = this.case_info;
clone.prop_info = this.prop_info;
clone.updated_on = this.updated_on;
clone.availability = this.availability;
return clone;
}
public Integer getMotor_id() {
return motor_id;
}
public void setMotor_id(Integer motor_id) {
this.motor_id = motor_id;
}
public String getManufacturer() {
return manufacturer;
}
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
public String getManufacturer_abbr() {
return manufacturer_abbr;
}
public void setManufacturer_abbr(String manufacturer_abbr) {
this.manufacturer_abbr = manufacturer_abbr;
}
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
public String getBrand_name() {
return brand_name;
}
public void setBrand_name(String brand_name) {
this.brand_name = brand_name;
}
public String getCommon_name() {
return common_name;
}
public void setCommon_name(String common_name) {
this.common_name = common_name;
}
public String getImpulse_class() {
return impulse_class;
}
public void setImpulse_class(String impulse_class) {
this.impulse_class = impulse_class;
}
public Float getDiameter() {
return diameter;
}
public void setDiameter(Float diameter) {
this.diameter = diameter;
}
public Float getLength() {
return length;
}
public void setLength(Float length) {
this.length = length;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getCert_org() {
return cert_org;
}
public void setCert_org(String cert_org) {
this.cert_org = cert_org;
}
public Float getAvg_thrust_n() {
return avg_thrust_n;
}
public void setAvg_thrust_n(Float avg_thrust_n) {
this.avg_thrust_n = avg_thrust_n;
}
public Float getMax_thrust_n() {
return max_thrust_n;
}
public void setMax_thrust_n(Float max_thrust_n) {
this.max_thrust_n = max_thrust_n;
}
public Float getTot_impulse_ns() {
return tot_impulse_ns;
}
public void setTot_impulse_ns(Float tot_impulse_ns) {
this.tot_impulse_ns = tot_impulse_ns;
}
public Float getBurn_time_s() {
return burn_time_s;
}
public void setBurn_time_s(Float burn_time_s) {
this.burn_time_s = burn_time_s;
}
public Integer getData_files() {
return data_files;
}
public void setData_files(Integer data_files) {
this.data_files = data_files;
}
public String getInfo_url() {
return info_url;
}
public void setInfo_url(String info_url) {
this.info_url = info_url;
}
public Double getTot_mass_g() {
return tot_mass_g;
}
public void setTot_mass_g(Double tot_mass_g) {
this.tot_mass_g = tot_mass_g;
}
public Double getProp_mass_g() {
return prop_mass_g;
}
public void setProp_mass_g(Double prop_mass_g) {
this.prop_mass_g = prop_mass_g;
}
public String getDelays() {
return delays;
}
public void setDelays(String delays) {
this.delays = delays;
}
public String getCase_info() {
return case_info;
}
public void setCase_info(String case_info) {
this.case_info = case_info;
}
public String getProp_info() {
return prop_info;
}
public void setProp_info(String prop_info) {
this.prop_info = prop_info;
}
public Date getUpdated_on() {
return updated_on;
}
public void setUpdated_on(Date updated_on) {
this.updated_on = updated_on;
}
public String getAvailability() {
return availability;
}
public void setAvailability(String avail) {
this.availability = avail;
}
@Override
public String toString() {
return "TCMotor [motor_id=" + motor_id + ", manufacturer="
+ manufacturer + ", manufacturer_abbr=" + manufacturer_abbr
+ ", designation=" + designation + ", brand_name=" + brand_name
+ ", common_name=" + common_name + ", impulse_class="
+ impulse_class + ", diameter=" + diameter + ", length="
+ length + ", type=" + type + ", cert_org=" + cert_org
+ ", avg_thrust_n=" + avg_thrust_n + ", max_thrust_n="
+ max_thrust_n + ", tot_impulse_ns=" + tot_impulse_ns
+ ", burn_time_s=" + burn_time_s + ", data_files=" + data_files
+ ", info_url=" + info_url + ", tot_mass_g=" + tot_mass_g
+ ", prop_mass_g=" + prop_mass_g + ", delays=" + delays
+ ", case_info=" + case_info + ", prop_info=" + prop_info
+ ", updated_on=" + updated_on + ", availability=" + availability + "]";
}
}

@ -1,83 +1,83 @@
package net.sf.openrocket.thrustcurve;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Collections;
import java.util.List;
import org.xml.sax.SAXException;
public abstract class ThrustCurveAPI {
public static SearchResponse doSearch(SearchRequest request) throws IOException, SAXException {
String requestString = request.toString();
// Froyo has troubles resolving URLS constructed with protocols. Because of this
// we need to do it in parts.
URL url = new URL("http", "www.thrustcurve.org", "/servlets/search");
OutputStream stream;
URLConnection conn = url.openConnection();
conn.setConnectTimeout(2000);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
stream = conn.getOutputStream();
stream.write(requestString.getBytes());
InputStream is = conn.getInputStream();
SearchResponse result = SearchResponseParser.parse(is);
return result;
}
public static List<MotorBurnFile> downloadData(Integer motor_id, String format) throws IOException, SAXException {
if (motor_id == null) {
return null;
}
DownloadRequest dr = new DownloadRequest();
dr.add(motor_id);
dr.setFormat(format);
String requestString = dr.toString();
// Froyo has troubles resolving URLS constructed with protocols. Because of this
// we need to do it in parts.
URL url = new URL("http", "www.thrustcurve.org", "/servlets/download");
OutputStream stream;
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.connect();
stream = conn.getOutputStream();
stream.write(requestString.getBytes());
if (conn.getResponseCode() == HttpURLConnection.HTTP_BAD_REQUEST) {
return Collections.emptyList();
}
InputStream is = conn.getInputStream();
DownloadResponse downloadResponse = DownloadResponseParser.parse(is);
return downloadResponse.getData(motor_id);
}
}
package net.sf.openrocket.thrustcurve;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Collections;
import java.util.List;
import org.xml.sax.SAXException;
public abstract class ThrustCurveAPI {
public static SearchResponse doSearch(SearchRequest request) throws IOException, SAXException {
String requestString = request.toString();
// Froyo has troubles resolving URLS constructed with protocols. Because of this
// we need to do it in parts.
URL url = new URL("http", "www.thrustcurve.org", "/servlets/search");
OutputStream stream;
URLConnection conn = url.openConnection();
conn.setConnectTimeout(2000);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
stream = conn.getOutputStream();
stream.write(requestString.getBytes());
InputStream is = conn.getInputStream();
SearchResponse result = SearchResponseParser.parse(is);
return result;
}
public static List<MotorBurnFile> downloadData(Integer motor_id, String format) throws IOException, SAXException {
if (motor_id == null) {
return null;
}
DownloadRequest dr = new DownloadRequest();
dr.add(motor_id);
dr.setFormat(format);
String requestString = dr.toString();
// Froyo has troubles resolving URLS constructed with protocols. Because of this
// we need to do it in parts.
URL url = new URL("http", "www.thrustcurve.org", "/servlets/download");
OutputStream stream;
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.connect();
stream = conn.getOutputStream();
stream.write(requestString.getBytes());
if (conn.getResponseCode() == HttpURLConnection.HTTP_BAD_REQUEST) {
return Collections.emptyList();
}
InputStream is = conn.getInputStream();
DownloadResponse downloadResponse = DownloadResponseParser.parse(is);
return downloadResponse.getData(motor_id);
}
}

@ -1,139 +1,139 @@
/*
* The Alphanum Algorithm is an improved sorting algorithm for strings
* containing numbers. Instead of sorting numbers in ASCII order like
* a standard sort, this algorithm sorts numbers in numeric order.
*
* The Alphanum Algorithm is discussed at http://www.DaveKoelle.com
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/*
* Subsequently this code had been hacked up to make it genericized and support
* folding upper/lower case.
*/
package net.sf.openrocket.util;
import java.text.Collator;
import java.util.Comparator;
/**
* This is an updated version with enhancements made by Daniel Migowski,
* Andre Bogus, and David Koelle
*
* To convert to use Templates (Java 1.5+):
* - Change "implements Comparator" to "implements Comparator<String>"
* - Change "compare(Object o1, Object o2)" to "compare(String s1, String s2)"
* - Remove the type checking and casting in compare().
*
* To use this class:
* Use the static "sort" method from the java.util.Collections class:
* Collections.sort(your list, new AlphanumComparator());
*/
public class AlphanumComparator implements Comparator<String>
{
private static final Collator sorter = Collator.getInstance();
static {
sorter.setStrength(Collator.TERTIARY);
sorter.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
}
private final boolean isDigit(char ch)
{
return ch >= 48 && ch <= 57;
}
/** Length of string is passed in for improved efficiency (only need to calculate it once) **/
private final String getChunk(String s, int slength, int marker)
{
StringBuilder chunk = new StringBuilder();
char c = s.charAt(marker);
chunk.append(c);
marker++;
if (isDigit(c))
{
while (marker < slength)
{
c = s.charAt(marker);
if (!isDigit(c))
break;
chunk.append(c);
marker++;
}
} else
{
while (marker < slength)
{
c = s.charAt(marker);
if (isDigit(c))
break;
chunk.append(c);
marker++;
}
}
return chunk.toString();
}
@Override
public int compare(String s1, String s2)
{
int thisMarker = 0;
int thatMarker = 0;
int s1Length = s1.length();
int s2Length = s2.length();
while (thisMarker < s1Length && thatMarker < s2Length)
{
String thisChunk = getChunk(s1, s1Length, thisMarker);
thisMarker += thisChunk.length();
String thatChunk = getChunk(s2, s2Length, thatMarker);
thatMarker += thatChunk.length();
// If both chunks contain numeric characters, sort them numerically
int result = 0;
if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0)))
{
// Simple chunk comparison by length.
int thisChunkLength = thisChunk.length();
result = thisChunkLength - thatChunk.length();
// If equal, the first different number counts
if (result == 0)
{
for (int i = 0; i < thisChunkLength; i++)
{
result = thisChunk.charAt(i) - thatChunk.charAt(i);
if (result != 0)
{
return result;
}
}
}
} else
{
result = sorter.compare(thisChunk, thatChunk);
}
if (result != 0)
return result;
}
return s1Length - s2Length;
}
}
/*
* The Alphanum Algorithm is an improved sorting algorithm for strings
* containing numbers. Instead of sorting numbers in ASCII order like
* a standard sort, this algorithm sorts numbers in numeric order.
*
* The Alphanum Algorithm is discussed at http://www.DaveKoelle.com
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/*
* Subsequently this code had been hacked up to make it genericized and support
* folding upper/lower case.
*/
package net.sf.openrocket.util;
import java.text.Collator;
import java.util.Comparator;
/**
* This is an updated version with enhancements made by Daniel Migowski,
* Andre Bogus, and David Koelle
*
* To convert to use Templates (Java 1.5+):
* - Change "implements Comparator" to "implements Comparator<String>"
* - Change "compare(Object o1, Object o2)" to "compare(String s1, String s2)"
* - Remove the type checking and casting in compare().
*
* To use this class:
* Use the static "sort" method from the java.util.Collections class:
* Collections.sort(your list, new AlphanumComparator());
*/
public class AlphanumComparator implements Comparator<String>
{
private static final Collator sorter = Collator.getInstance();
static {
sorter.setStrength(Collator.TERTIARY);
sorter.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
}
private final boolean isDigit(char ch)
{
return ch >= 48 && ch <= 57;
}
/** Length of string is passed in for improved efficiency (only need to calculate it once) **/
private final String getChunk(String s, int slength, int marker)
{
StringBuilder chunk = new StringBuilder();
char c = s.charAt(marker);
chunk.append(c);
marker++;
if (isDigit(c))
{
while (marker < slength)
{
c = s.charAt(marker);
if (!isDigit(c))
break;
chunk.append(c);
marker++;
}
} else
{
while (marker < slength)
{
c = s.charAt(marker);
if (isDigit(c))
break;
chunk.append(c);
marker++;
}
}
return chunk.toString();
}
@Override
public int compare(String s1, String s2)
{
int thisMarker = 0;
int thatMarker = 0;
int s1Length = s1.length();
int s2Length = s2.length();
while (thisMarker < s1Length && thatMarker < s2Length)
{
String thisChunk = getChunk(s1, s1Length, thisMarker);
thisMarker += thisChunk.length();
String thatChunk = getChunk(s2, s2Length, thatMarker);
thatMarker += thatChunk.length();
// If both chunks contain numeric characters, sort them numerically
int result = 0;
if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0)))
{
// Simple chunk comparison by length.
int thisChunkLength = thisChunk.length();
result = thisChunkLength - thatChunk.length();
// If equal, the first different number counts
if (result == 0)
{
for (int i = 0; i < thisChunkLength; i++)
{
result = thisChunk.charAt(i) - thatChunk.charAt(i);
if (result != 0)
{
return result;
}
}
}
} else
{
result = sorter.compare(thisChunk, thatChunk);
}
if (result != 0)
return result;
}
return s1Length - s2Length;
}
}

@ -1,93 +1,93 @@
package net.sf.openrocket.util;
import java.io.IOException;
import java.io.InputStream;
import java.util.MissingResourceException;
import java.util.Properties;
public class BuildProperties {
private static final Properties PROPERTIES;
private static final String BUILD_VERSION;
private static final String BUILD_COPYRIGHT;
private static final String BUILD_SOURCE;
private static final boolean DEFAULT_CHECK_UPDATES;
private static final boolean DEFAULT_CHECK_BETA_UPDATES;
/**
* Return the OpenRocket version number.
*/
public static String getVersion() {
return BUILD_VERSION;
}
/**
* Return the OpenRocket build source (e.g. "default" or "Debian")
*/
public static String getBuildSource() {
return BUILD_SOURCE;
}
public static boolean getDefaultCheckUpdates() {
return DEFAULT_CHECK_UPDATES;
}
public static boolean getDefaultCheckBetaUpdates() {
return DEFAULT_CHECK_BETA_UPDATES;
}
public static String getCopyrightYear() {
return BUILD_COPYRIGHT;
}
static {
try {
InputStream is = BuildProperties.class.getClassLoader().getResourceAsStream("build.properties");
if (is == null) {
throw new MissingResourceException(
"build.properties not found, distribution built wrong" +
" classpath:" + System.getProperty("java.class.path"),
"build.properties", "build.version");
}
PROPERTIES = new Properties();
PROPERTIES.load(is);
is.close();
String version = PROPERTIES.getProperty("build.version");
if (version == null) {
throw new MissingResourceException(
"build.version not found in property file",
"build.properties", "build.version");
}
BUILD_VERSION = version.trim();
BUILD_SOURCE = PROPERTIES.getProperty("build.source");
if (BUILD_SOURCE == null) {
throw new MissingResourceException(
"build.source not found in property file",
"build.properties", "build.source");
}
String value = PROPERTIES.getProperty("build.checkupdates");
if (value != null)
DEFAULT_CHECK_UPDATES = Boolean.parseBoolean(value);
else
DEFAULT_CHECK_UPDATES = true;
value = PROPERTIES.getProperty("build.checkbetaupdates");
if (value != null)
DEFAULT_CHECK_BETA_UPDATES = Boolean.parseBoolean(value);
else
DEFAULT_CHECK_BETA_UPDATES = true;
BUILD_COPYRIGHT = PROPERTIES.getProperty("build.copyright", "2021");
} catch (IOException e) {
throw new MissingResourceException(
"Error reading build.properties",
"build.properties", "build.version");
}
}
}
package net.sf.openrocket.util;
import java.io.IOException;
import java.io.InputStream;
import java.util.MissingResourceException;
import java.util.Properties;
public class BuildProperties {
private static final Properties PROPERTIES;
private static final String BUILD_VERSION;
private static final String BUILD_COPYRIGHT;
private static final String BUILD_SOURCE;
private static final boolean DEFAULT_CHECK_UPDATES;
private static final boolean DEFAULT_CHECK_BETA_UPDATES;
/**
* Return the OpenRocket version number.
*/
public static String getVersion() {
return BUILD_VERSION;
}
/**
* Return the OpenRocket build source (e.g. "default" or "Debian")
*/
public static String getBuildSource() {
return BUILD_SOURCE;
}
public static boolean getDefaultCheckUpdates() {
return DEFAULT_CHECK_UPDATES;
}
public static boolean getDefaultCheckBetaUpdates() {
return DEFAULT_CHECK_BETA_UPDATES;
}
public static String getCopyrightYear() {
return BUILD_COPYRIGHT;
}
static {
try {
InputStream is = BuildProperties.class.getClassLoader().getResourceAsStream("build.properties");
if (is == null) {
throw new MissingResourceException(
"build.properties not found, distribution built wrong" +
" classpath:" + System.getProperty("java.class.path"),
"build.properties", "build.version");
}
PROPERTIES = new Properties();
PROPERTIES.load(is);
is.close();
String version = PROPERTIES.getProperty("build.version");
if (version == null) {
throw new MissingResourceException(
"build.version not found in property file",
"build.properties", "build.version");
}
BUILD_VERSION = version.trim();
BUILD_SOURCE = PROPERTIES.getProperty("build.source");
if (BUILD_SOURCE == null) {
throw new MissingResourceException(
"build.source not found in property file",
"build.properties", "build.source");
}
String value = PROPERTIES.getProperty("build.checkupdates");
if (value != null)
DEFAULT_CHECK_UPDATES = Boolean.parseBoolean(value);
else
DEFAULT_CHECK_UPDATES = true;
value = PROPERTIES.getProperty("build.checkbetaupdates");
if (value != null)
DEFAULT_CHECK_BETA_UPDATES = Boolean.parseBoolean(value);
else
DEFAULT_CHECK_BETA_UPDATES = true;
BUILD_COPYRIGHT = PROPERTIES.getProperty("build.copyright", "2021");
} catch (IOException e) {
throw new MissingResourceException(
"Error reading build.properties",
"build.properties", "build.version");
}
}
}

@ -1,69 +1,69 @@
package net.sf.openrocket.util;
public class Color {
public static Color BLACK = new Color(255,255,255);
public static Color INVISIBLE = new Color(1, 1, 1, 0);
public static Color DARK_RED = new Color(200, 0, 0);
private int red;
private int green;
private int blue;
private int alpha;
public Color( int red, int green, int blue ) {
this.red = red;
this.green = green;
this.blue = blue;
this.alpha = 255;
}
public Color( int red, int green, int blue, int alpha ) {
this.red = red;
this.green = green;
this.blue = blue;
this.alpha = alpha;
}
public int getRed() {
return red;
}
public void setRed(int red) {
this.red = red;
}
public int getGreen() {
return green;
}
public void setGreen(int green) {
this.green = green;
}
public int getBlue() {
return blue;
}
public void setBlue(int blue) {
this.blue = blue;
}
public int getAlpha() {
return alpha;
}
public void setAlpha(int alpha) {
this.alpha = alpha;
}
@Override
public String toString() {
return "Color [r=" + red + ", g=" + green + ", b=" + blue + ", a=" + alpha + "]";
}
public java.awt.Color toAWTColor() {
return new java.awt.Color(red, green, blue, alpha);
}
}
package net.sf.openrocket.util;
public class Color {
public static Color BLACK = new Color(255,255,255);
public static Color INVISIBLE = new Color(1, 1, 1, 0);
public static Color DARK_RED = new Color(200, 0, 0);
private int red;
private int green;
private int blue;
private int alpha;
public Color( int red, int green, int blue ) {
this.red = red;
this.green = green;
this.blue = blue;
this.alpha = 255;
}
public Color( int red, int green, int blue, int alpha ) {
this.red = red;
this.green = green;
this.blue = blue;
this.alpha = alpha;
}
public int getRed() {
return red;
}
public void setRed(int red) {
this.red = red;
}
public int getGreen() {
return green;
}
public void setGreen(int green) {
this.green = green;
}
public int getBlue() {
return blue;
}
public void setBlue(int blue) {
this.blue = blue;
}
public int getAlpha() {
return alpha;
}
public void setAlpha(int alpha) {
this.alpha = alpha;
}
@Override
public String toString() {
return "Color [r=" + red + ", g=" + green + ", b=" + blue + ", a=" + alpha + "]";
}
public java.awt.Color toAWTColor() {
return new java.awt.Color(red, green, blue, alpha);
}
}

@ -1,10 +1,10 @@
package net.sf.openrocket.util;
import java.util.EventListener;
import java.util.EventObject;
public interface StateChangeListener extends EventListener {
public void stateChanged( EventObject e );
}
package net.sf.openrocket.util;
import java.util.EventListener;
import java.util.EventObject;
public interface StateChangeListener extends EventListener {
public void stateChanged( EventObject e );
}

@ -1,40 +1,40 @@
<engine-database>
<engine-list>
<engine FDiv="10" FFix="1" FStep="-1." Isp="71.7" Itot="2.32" Type="single-use" auto-calc-cg="1" auto-calc-mass="1" avgThrust="3.178" burn-time="0.73" cgDiv="10" cgFix="1" cgStep="-1." code="A8" delays="3,5" dia="18." exitDia="0." initWt="16.35" len="70." mDiv="10" mFix="1" mStep="-1." massFrac="20.18" mfg="Estes" peakThrust="9.73" propWt="3.3" tDiv="10" tFix="1" tStep="-1." throatDia="0.">
<comments>Estes A8 RASP.ENG file made from NAR published data
File produced October 3, 2000
The total impulse, peak thrust, average thrust and burn time are
the same as the averaged static test data on the NAR web site in
the certification file. The curve drawn with these data points is as
close to the certification curve as can be with such a limited
number of points (32) allowed with wRASP up to v1.6.
</comments>
<data>
<eng-data cg="35." f="0." m="3.3" t="0."/>
<eng-data cg="35." f="0.512" m="3.28507" t="0.041"/>
<eng-data cg="35." f="2.115" m="3.20474" t="0.084"/>
<eng-data cg="35." f="4.358" m="3.0068" t="0.127"/>
<eng-data cg="35." f="6.794" m="2.6975" t="0.166"/>
<eng-data cg="35." f="8.588" m="2.41309" t="0.192"/>
<eng-data cg="35." f="9.294" m="2.23506" t="0.206"/>
<eng-data cg="35." f="9.73" m="1.96448" t="0.226"/>
<eng-data cg="35." f="8.845" m="1.83238" t="0.236"/>
<eng-data cg="35." f="7.179" m="1.70703" t="0.247"/>
<eng-data cg="35." f="5.063" m="1.58515" t="0.261"/>
<eng-data cg="35." f="3.717" m="1.48525" t="0.277"/>
<eng-data cg="35." f="3.205" m="1.3425" t="0.306"/>
<eng-data cg="35." f="2.884" m="1.14764" t="0.351"/>
<eng-data cg="35." f="2.499" m="0.94092" t="0.405"/>
<eng-data cg="35." f="2.371" m="0.726196" t="0.467"/>
<eng-data cg="35." f="2.307" m="0.509957" t="0.532"/>
<eng-data cg="35." f="2.371" m="0.320333" t="0.589"/>
<eng-data cg="35." f="2.371" m="0.175326" t="0.632"/>
<eng-data cg="35." f="2.243" m="0.109701" t="0.652"/>
<eng-data cg="35." f="1.794" m="0.0637665" t="0.668"/>
<eng-data cg="35." f="1.153" m="0.0302344" t="0.684"/>
<eng-data cg="35." f="0.448" m="0.00860204" t="0.703"/>
<eng-data cg="35." f="0." m="0." t="0.73"/>
</data>
</engine>
</engine-list>
</engine-database>
<engine-database>
<engine-list>
<engine FDiv="10" FFix="1" FStep="-1." Isp="71.7" Itot="2.32" Type="single-use" auto-calc-cg="1" auto-calc-mass="1" avgThrust="3.178" burn-time="0.73" cgDiv="10" cgFix="1" cgStep="-1." code="A8" delays="3,5" dia="18." exitDia="0." initWt="16.35" len="70." mDiv="10" mFix="1" mStep="-1." massFrac="20.18" mfg="Estes" peakThrust="9.73" propWt="3.3" tDiv="10" tFix="1" tStep="-1." throatDia="0.">
<comments>Estes A8 RASP.ENG file made from NAR published data
File produced October 3, 2000
The total impulse, peak thrust, average thrust and burn time are
the same as the averaged static test data on the NAR web site in
the certification file. The curve drawn with these data points is as
close to the certification curve as can be with such a limited
number of points (32) allowed with wRASP up to v1.6.
</comments>
<data>
<eng-data cg="35." f="0." m="3.3" t="0."/>
<eng-data cg="35." f="0.512" m="3.28507" t="0.041"/>
<eng-data cg="35." f="2.115" m="3.20474" t="0.084"/>
<eng-data cg="35." f="4.358" m="3.0068" t="0.127"/>
<eng-data cg="35." f="6.794" m="2.6975" t="0.166"/>
<eng-data cg="35." f="8.588" m="2.41309" t="0.192"/>
<eng-data cg="35." f="9.294" m="2.23506" t="0.206"/>
<eng-data cg="35." f="9.73" m="1.96448" t="0.226"/>
<eng-data cg="35." f="8.845" m="1.83238" t="0.236"/>
<eng-data cg="35." f="7.179" m="1.70703" t="0.247"/>
<eng-data cg="35." f="5.063" m="1.58515" t="0.261"/>
<eng-data cg="35." f="3.717" m="1.48525" t="0.277"/>
<eng-data cg="35." f="3.205" m="1.3425" t="0.306"/>
<eng-data cg="35." f="2.884" m="1.14764" t="0.351"/>
<eng-data cg="35." f="2.499" m="0.94092" t="0.405"/>
<eng-data cg="35." f="2.371" m="0.726196" t="0.467"/>
<eng-data cg="35." f="2.307" m="0.509957" t="0.532"/>
<eng-data cg="35." f="2.371" m="0.320333" t="0.589"/>
<eng-data cg="35." f="2.371" m="0.175326" t="0.632"/>
<eng-data cg="35." f="2.243" m="0.109701" t="0.652"/>
<eng-data cg="35." f="1.794" m="0.0637665" t="0.668"/>
<eng-data cg="35." f="1.153" m="0.0302344" t="0.684"/>
<eng-data cg="35." f="0.448" m="0.00860204" t="0.703"/>
<eng-data cg="35." f="0." m="0." t="0.73"/>
</data>
</engine>
</engine-list>
</engine-database>

@ -1,24 +1,24 @@
D10 18 70 7 0.009800000000000001 0.0259 AT
0.0070 23.0
0.018 25.0
0.027 20.25
0.066 20.25
0.073 18.5
0.094 20.25
0.112 20.75
0.137 19.75
0.163 21.5
0.202 20.75
0.231 20.75
0.254 22.75
0.27 20.75
0.504 20.0
0.536 18.25
0.607 17.0
0.687 14.75
0.751 14.25
0.84 11.25
0.998 8.25
1.024 8.25
1.248 2.5
1.385 0.0
D10 18 70 7 0.009800000000000001 0.0259 AT
0.0070 23.0
0.018 25.0
0.027 20.25
0.066 20.25
0.073 18.5
0.094 20.25
0.112 20.75
0.137 19.75
0.163 21.5
0.202 20.75
0.231 20.75
0.254 22.75
0.27 20.75
0.504 20.0
0.536 18.25
0.607 17.0
0.687 14.75
0.751 14.25
0.84 11.25
0.998 8.25
1.024 8.25
1.248 2.5
1.385 0.0

@ -1,52 +1,52 @@
<engine-database>
<engine-list>
<engine mfg="Cesaroni Technology Inc." code="G115-13A" Type="reloadable" dia="38."
len="127." initWt="195." propWt="61.8" delays="13" auto-calc-mass="1"
auto-calc-cg="1" avgThrust="113.512" peakThrust="131.895" throatDia="0."
exitDia="0." Itot="140.755" burn-time="1.24" massFrac="31.69" Isp="232.25"
tDiv="10" tStep="-1." tFix="1" FDiv="10" FStep="-1." FFix="1" mDiv="10"
mStep="-1." mFix="1" cgDiv="10" cgStep="-1." cgFix="1">
<data>
<eng-data t="0." f="0." m="61.8" cg="63.5"/>
<eng-data t="0.00787402" f="10.3447" m="61.7821" cg="63.5"/>
<eng-data t="0.0183727" f="117.671" m="61.4871" cg="63.5"/>
<eng-data t="0.0209974" f="128.447" m="61.3453" cg="63.5"/>
<eng-data t="0.0446194" f="131.895" m="59.9952" cg="63.5"/>
<eng-data t="0.0577428" f="125.861" m="59.2526" cg="63.5"/>
<eng-data t="0.0629921" f="119.395" m="58.97" cg="63.5"/>
<eng-data t="0.0787402" f="113.792" m="58.1638" cg="63.5"/>
<eng-data t="0.107612" f="115.947" m="56.7077" cg="63.5"/>
<eng-data t="0.149606" f="118.964" m="54.542" cg="63.5"/>
<eng-data t="0.188976" f="119.395" m="52.4819" cg="63.5"/>
<eng-data t="0.233596" f="121.981" m="50.1176" cg="63.5"/>
<eng-data t="0.278215" f="122.412" m="47.7237" cg="63.5"/>
<eng-data t="0.322835" f="122.843" m="45.3213" cg="63.5"/>
<eng-data t="0.380577" f="123.274" m="42.2014" cg="63.5"/>
<eng-data t="0.440945" f="122.843" m="38.9398" cg="63.5"/>
<eng-data t="0.480315" f="123.274" m="36.8126" cg="63.5"/>
<eng-data t="0.540682" f="122.843" m="33.5509" cg="63.5"/>
<eng-data t="0.590551" f="122.412" m="30.866" cg="63.5"/>
<eng-data t="0.622047" f="120.688" m="29.1851" cg="63.5"/>
<eng-data t="0.67979" f="120.257" m="26.1308" cg="63.5"/>
<eng-data t="0.734908" f="119.395" m="23.231" cg="63.5"/>
<eng-data t="0.790026" f="117.671" m="20.3625" cg="63.5"/>
<eng-data t="0.845144" f="116.809" m="17.5253" cg="63.5"/>
<eng-data t="0.88189" f="116.378" m="15.6442" cg="63.5"/>
<eng-data t="0.929134" f="113.361" m="13.2615" cg="63.5"/>
<eng-data t="0.979003" f="113.361" m="10.7794" cg="63.5"/>
<eng-data t="1.0315" f="111.206" m="8.19152" cg="63.5"/>
<eng-data t="1.07087" f="108.188" m="6.29532" cg="63.5"/>
<eng-data t="1.11286" f="108.188" m="4.30052" cg="63.5"/>
<eng-data t="1.16535" f="106.033" m="1.83186" cg="63.5"/>
<eng-data t="1.18373" f="112.499" m="0.95044" cg="63.5"/>
<eng-data t="1.18635" f="96.5506" m="0.829987" cg="63.5"/>
<eng-data t="1.19685" f="81.0335" m="0.420696" cg="63.5"/>
<eng-data t="1.2021" f="51.7235" m="0.267708" cg="63.5"/>
<eng-data t="1.2126" f="30.172" m="0.0789575" cg="63.5"/>
<eng-data t="1.21522" f="16.8101" m="0.0518866" cg="63.5"/>
<eng-data t="1.21785" f="7.75853" m="0.0377303" cg="63.5"/>
<eng-data t="1.24" f="0." m="0." cg="63.5"/>
</data>
</engine>
</engine-list>
</engine-database>
<engine-database>
<engine-list>
<engine mfg="Cesaroni Technology Inc." code="G115-13A" Type="reloadable" dia="38."
len="127." initWt="195." propWt="61.8" delays="13" auto-calc-mass="1"
auto-calc-cg="1" avgThrust="113.512" peakThrust="131.895" throatDia="0."
exitDia="0." Itot="140.755" burn-time="1.24" massFrac="31.69" Isp="232.25"
tDiv="10" tStep="-1." tFix="1" FDiv="10" FStep="-1." FFix="1" mDiv="10"
mStep="-1." mFix="1" cgDiv="10" cgStep="-1." cgFix="1">
<data>
<eng-data t="0." f="0." m="61.8" cg="63.5"/>
<eng-data t="0.00787402" f="10.3447" m="61.7821" cg="63.5"/>
<eng-data t="0.0183727" f="117.671" m="61.4871" cg="63.5"/>
<eng-data t="0.0209974" f="128.447" m="61.3453" cg="63.5"/>
<eng-data t="0.0446194" f="131.895" m="59.9952" cg="63.5"/>
<eng-data t="0.0577428" f="125.861" m="59.2526" cg="63.5"/>
<eng-data t="0.0629921" f="119.395" m="58.97" cg="63.5"/>
<eng-data t="0.0787402" f="113.792" m="58.1638" cg="63.5"/>
<eng-data t="0.107612" f="115.947" m="56.7077" cg="63.5"/>
<eng-data t="0.149606" f="118.964" m="54.542" cg="63.5"/>
<eng-data t="0.188976" f="119.395" m="52.4819" cg="63.5"/>
<eng-data t="0.233596" f="121.981" m="50.1176" cg="63.5"/>
<eng-data t="0.278215" f="122.412" m="47.7237" cg="63.5"/>
<eng-data t="0.322835" f="122.843" m="45.3213" cg="63.5"/>
<eng-data t="0.380577" f="123.274" m="42.2014" cg="63.5"/>
<eng-data t="0.440945" f="122.843" m="38.9398" cg="63.5"/>
<eng-data t="0.480315" f="123.274" m="36.8126" cg="63.5"/>
<eng-data t="0.540682" f="122.843" m="33.5509" cg="63.5"/>
<eng-data t="0.590551" f="122.412" m="30.866" cg="63.5"/>
<eng-data t="0.622047" f="120.688" m="29.1851" cg="63.5"/>
<eng-data t="0.67979" f="120.257" m="26.1308" cg="63.5"/>
<eng-data t="0.734908" f="119.395" m="23.231" cg="63.5"/>
<eng-data t="0.790026" f="117.671" m="20.3625" cg="63.5"/>
<eng-data t="0.845144" f="116.809" m="17.5253" cg="63.5"/>
<eng-data t="0.88189" f="116.378" m="15.6442" cg="63.5"/>
<eng-data t="0.929134" f="113.361" m="13.2615" cg="63.5"/>
<eng-data t="0.979003" f="113.361" m="10.7794" cg="63.5"/>
<eng-data t="1.0315" f="111.206" m="8.19152" cg="63.5"/>
<eng-data t="1.07087" f="108.188" m="6.29532" cg="63.5"/>
<eng-data t="1.11286" f="108.188" m="4.30052" cg="63.5"/>
<eng-data t="1.16535" f="106.033" m="1.83186" cg="63.5"/>
<eng-data t="1.18373" f="112.499" m="0.95044" cg="63.5"/>
<eng-data t="1.18635" f="96.5506" m="0.829987" cg="63.5"/>
<eng-data t="1.19685" f="81.0335" m="0.420696" cg="63.5"/>
<eng-data t="1.2021" f="51.7235" m="0.267708" cg="63.5"/>
<eng-data t="1.2126" f="30.172" m="0.0789575" cg="63.5"/>
<eng-data t="1.21522" f="16.8101" m="0.0518866" cg="63.5"/>
<eng-data t="1.21785" f="7.75853" m="0.0377303" cg="63.5"/>
<eng-data t="1.24" f="0." m="0." cg="63.5"/>
</data>
</engine>
</engine-list>
</engine-database>

@ -1,34 +1,34 @@
package net.sf.openrocket.util.BaseTestCase;
import net.sf.openrocket.ServicesForTesting;
import net.sf.openrocket.l10n.DebugTranslator;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.plugin.PluginModule;
import net.sf.openrocket.startup.Application;
import org.junit.BeforeClass;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.util.Modules;
public class BaseTestCase {
@BeforeClass
public static void setUp() throws Exception {
Module applicationModule = new ServicesForTesting();
Module debugTranslator = new AbstractModule() {
@Override
protected void configure() {
bind(Translator.class).toInstance(new DebugTranslator(null));
}
};
Module pluginModule = new PluginModule();
Injector injector = Guice.createInjector(Modules.override(applicationModule).with(debugTranslator), pluginModule);
Application.setInjector(injector);
}
}
package net.sf.openrocket.util.BaseTestCase;
import net.sf.openrocket.ServicesForTesting;
import net.sf.openrocket.l10n.DebugTranslator;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.plugin.PluginModule;
import net.sf.openrocket.startup.Application;
import org.junit.BeforeClass;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.util.Modules;
public class BaseTestCase {
@BeforeClass
public static void setUp() throws Exception {
Module applicationModule = new ServicesForTesting();
Module debugTranslator = new AbstractModule() {
@Override
protected void configure() {
bind(Translator.class).toInstance(new DebugTranslator(null));
}
};
Module pluginModule = new PluginModule();
Injector injector = Guice.createInjector(Modules.override(applicationModule).with(debugTranslator), pluginModule);
Application.setInjector(injector);
}
}

@ -1,143 +1,143 @@
--Do not remove this if you are using--
Original Author: Remiz Rahnas
Original Author URL: http://www.htmlremix.com
Published date: 2008/09/24
Changes by Nick Fetchak:
- IE8 standards mode compatibility
- VML elements now positioned behind original box rather than inside of it - should be less prone to breakage
Published date : 2009/11/18
<public:attach event="oncontentready" onevent="oncontentready('v08vnSVo78t4JfjH')" />
<script type="text/javascript">
// findPos() borrowed from http://www.quirksmode.org/js/findpos.html
function findPos(obj) {
var curleft = curtop = 0;
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
}
return({
'x': curleft,
'y': curtop
});
}
function oncontentready(classID) {
if (this.className.match(classID)) { return(false); }
if (!document.namespaces.v) { document.namespaces.add("v", "urn:schemas-microsoft-com:vml"); }
this.className = this.className.concat(' ', classID);
var arcSize = Math.min(parseInt(this.currentStyle['-moz-border-radius'] ||
this.currentStyle['-webkit-border-radius'] ||
this.currentStyle['border-radius'] ||
this.currentStyle['-khtml-border-radius']) /
Math.min(this.offsetWidth, this.offsetHeight), 1);
var fillColor = this.currentStyle.backgroundColor;
var fillSrc = this.currentStyle.backgroundImage.replace(/^url\("(.+)"\)$/, '$1');
var strokeColor = this.currentStyle.borderColor;
var strokeWeight = parseInt(this.currentStyle.borderWidth);
var stroked = 'true';
if (isNaN(strokeWeight)) {
strokeWeight = 0;
strokeColor = fillColor;
stroked = 'false';
}
this.style.background = 'transparent';
this.style.borderColor = 'transparent';
// Find which element provides position:relative for the target element (default to BODY)
var el = this;
var limit = 100, i = 0;
while ((typeof(el) != 'unknown') && (el.currentStyle.position != 'relative') && (el.tagName != 'BODY')) {
el = el.parentElement;
i++;
if (i >= limit) { return(false); }
}
var el_zindex = parseInt(el.currentStyle.zIndex);
if (isNaN(el_zindex)) { el_zindex = 0; }
//alert('got tag '+ el.tagName +' with pos '+ el.currentStyle.position);
var rect_size = {
'width': this.offsetWidth - strokeWeight,
'height': this.offsetHeight - strokeWeight
};
var el_pos = findPos(el);
var this_pos = findPos(this);
this_pos.y = this_pos.y + (0.5 * strokeWeight) - el_pos.y;
this_pos.x = this_pos.x + (0.5 * strokeWeight) - el_pos.x;
var rect = document.createElement('v:roundrect');
rect.arcsize = arcSize +'px';
rect.strokecolor = strokeColor;
rect.strokeWeight = strokeWeight +'px';
rect.stroked = stroked;
rect.style.display = 'block';
rect.style.position = 'absolute';
rect.style.top = this_pos.y +'px';
rect.style.left = this_pos.x +'px';
rect.style.width = rect_size.width +'px';
rect.style.height = rect_size.height +'px';
rect.style.antialias = true;
rect.style.zIndex = el_zindex - 1;
var fill = document.createElement('v:fill');
fill.color = fillColor;
fill.src = fillSrc;
fill.type = 'tile';
rect.appendChild(fill);
el.appendChild(rect);
var css = el.document.createStyleSheet();
css.addRule("v\\:roundrect", "behavior: url(#default#VML)");
css.addRule("v\\:fill", "behavior: url(#default#VML)");
isIE6 = /msie|MSIE 6/.test(navigator.userAgent);
// IE6 doesn't support transparent borders, use padding to offset original element
if (isIE6 && (strokeWeight > 0)) {
this.style.borderStyle = 'none';
this.style.paddingTop = parseInt(this.currentStyle.paddingTop || 0) + strokeWeight;
this.style.paddingBottom = parseInt(this.currentStyle.paddingBottom || 0) + strokeWeight;
}
if (typeof(window.rounded_elements) == 'undefined') {
window.rounded_elements = new Array();
if (typeof(window.onresize) == 'function') { window.previous_onresize = window.onresize; }
window.onresize = window_resize;
}
this.element.vml = rect;
window.rounded_elements.push(this.element);
}
function window_resize() {
if (typeof(window.rounded_elements) == 'undefined') { return(false); }
for (var i in window.rounded_elements) {
var el = window.rounded_elements[i];
var strokeWeight = parseInt(el.currentStyle.borderWidth);
if (isNaN(strokeWeight)) { strokeWeight = 0; }
var parent_pos = findPos(el.vml.parentNode);
var pos = findPos(el);
pos.y = pos.y + (0.5 * strokeWeight) - parent_pos.y;
pos.x = pos.x + (0.5 * strokeWeight) - parent_pos.x;
el.vml.style.top = pos.y +'px';
el.vml.style.left = pos.x +'px';
}
if (typeof(window.previous_onresize) == 'function') { window.previous_onresize(); }
}
</script>
--Do not remove this if you are using--
Original Author: Remiz Rahnas
Original Author URL: http://www.htmlremix.com
Published date: 2008/09/24
Changes by Nick Fetchak:
- IE8 standards mode compatibility
- VML elements now positioned behind original box rather than inside of it - should be less prone to breakage
Published date : 2009/11/18
<public:attach event="oncontentready" onevent="oncontentready('v08vnSVo78t4JfjH')" />
<script type="text/javascript">
// findPos() borrowed from http://www.quirksmode.org/js/findpos.html
function findPos(obj) {
var curleft = curtop = 0;
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
}
return({
'x': curleft,
'y': curtop
});
}
function oncontentready(classID) {
if (this.className.match(classID)) { return(false); }
if (!document.namespaces.v) { document.namespaces.add("v", "urn:schemas-microsoft-com:vml"); }
this.className = this.className.concat(' ', classID);
var arcSize = Math.min(parseInt(this.currentStyle['-moz-border-radius'] ||
this.currentStyle['-webkit-border-radius'] ||
this.currentStyle['border-radius'] ||
this.currentStyle['-khtml-border-radius']) /
Math.min(this.offsetWidth, this.offsetHeight), 1);
var fillColor = this.currentStyle.backgroundColor;
var fillSrc = this.currentStyle.backgroundImage.replace(/^url\("(.+)"\)$/, '$1');
var strokeColor = this.currentStyle.borderColor;
var strokeWeight = parseInt(this.currentStyle.borderWidth);
var stroked = 'true';
if (isNaN(strokeWeight)) {
strokeWeight = 0;
strokeColor = fillColor;
stroked = 'false';
}
this.style.background = 'transparent';
this.style.borderColor = 'transparent';
// Find which element provides position:relative for the target element (default to BODY)
var el = this;
var limit = 100, i = 0;
while ((typeof(el) != 'unknown') && (el.currentStyle.position != 'relative') && (el.tagName != 'BODY')) {
el = el.parentElement;
i++;
if (i >= limit) { return(false); }
}
var el_zindex = parseInt(el.currentStyle.zIndex);
if (isNaN(el_zindex)) { el_zindex = 0; }
//alert('got tag '+ el.tagName +' with pos '+ el.currentStyle.position);
var rect_size = {
'width': this.offsetWidth - strokeWeight,
'height': this.offsetHeight - strokeWeight
};
var el_pos = findPos(el);
var this_pos = findPos(this);
this_pos.y = this_pos.y + (0.5 * strokeWeight) - el_pos.y;
this_pos.x = this_pos.x + (0.5 * strokeWeight) - el_pos.x;
var rect = document.createElement('v:roundrect');
rect.arcsize = arcSize +'px';
rect.strokecolor = strokeColor;
rect.strokeWeight = strokeWeight +'px';
rect.stroked = stroked;
rect.style.display = 'block';
rect.style.position = 'absolute';
rect.style.top = this_pos.y +'px';
rect.style.left = this_pos.x +'px';
rect.style.width = rect_size.width +'px';
rect.style.height = rect_size.height +'px';
rect.style.antialias = true;
rect.style.zIndex = el_zindex - 1;
var fill = document.createElement('v:fill');
fill.color = fillColor;
fill.src = fillSrc;
fill.type = 'tile';
rect.appendChild(fill);
el.appendChild(rect);
var css = el.document.createStyleSheet();
css.addRule("v\\:roundrect", "behavior: url(#default#VML)");
css.addRule("v\\:fill", "behavior: url(#default#VML)");
isIE6 = /msie|MSIE 6/.test(navigator.userAgent);
// IE6 doesn't support transparent borders, use padding to offset original element
if (isIE6 && (strokeWeight > 0)) {
this.style.borderStyle = 'none';
this.style.paddingTop = parseInt(this.currentStyle.paddingTop || 0) + strokeWeight;
this.style.paddingBottom = parseInt(this.currentStyle.paddingBottom || 0) + strokeWeight;
}
if (typeof(window.rounded_elements) == 'undefined') {
window.rounded_elements = new Array();
if (typeof(window.onresize) == 'function') { window.previous_onresize = window.onresize; }
window.onresize = window_resize;
}
this.element.vml = rect;
window.rounded_elements.push(this.element);
}
function window_resize() {
if (typeof(window.rounded_elements) == 'undefined') { return(false); }
for (var i in window.rounded_elements) {
var el = window.rounded_elements[i];
var strokeWeight = parseInt(el.currentStyle.borderWidth);
if (isNaN(strokeWeight)) { strokeWeight = 0; }
var parent_pos = findPos(el.vml.parentNode);
var pos = findPos(el);
pos.y = pos.y + (0.5 * strokeWeight) - parent_pos.y;
pos.x = pos.x + (0.5 * strokeWeight) - parent_pos.x;
el.vml.style.top = pos.y +'px';
el.vml.style.left = pos.x +'px';
}
if (typeof(window.previous_onresize) == 'function') { window.previous_onresize(); }
}
</script>

@ -1,116 +1,116 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>OpenRocket &mdash; Support and contact information</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="keywords" content="OpenRocket, model rocket, simulator, simulation, rocketry" />
<link rel="stylesheet" type="text/css" href="layout.css" />
<meta name="Generator" content="htp 1.18" />
</head>
<body class="page_contact">
<!--[if lte IE 6]>
<div id="iewarn">
You are using a browser that is <strong>8 years old!</strong>
&nbsp;&nbsp;&nbsp;
In Internet-years that is <em>prehistoric!</em><br/>
For the sanity of all webmasterkind,
<em>please <a href="http://www.mozilla.com/">upgrade</a></em>. It's easy!
</div>
<![endif]-->
<div class="menucontainer">
<div class="menu">
<div class="icon"><a href="index.html"></a></div>
<ul>
<li><a href="index.html">OpenRocket</a></li>
<li><a href="features.html">Features and screenshots</a></li>
<li><a href="download.html">Download</a></li>
<li><a href="documentation.html">Documentation</a></li>
<li><a href="http://wiki.openrocket.info/">Wiki pages</a></li>
<li><a href="http://openrocket.trans.free.fr/">Translations</a></li>
<li><a href="getinvolved.html">Get involved!</a></li>
<li><a href="contact.html">
Mailing lists<br/>
Support forums<br/>
Contact info</a></li>
<!--
<li><a href="report.html">
Report a bug<br/>
Request a feature</a></li>
-->
<li><a href="license.html">License</a></li>
</ul>
<div class="logo">
<a href="http://sourceforge.net/projects/openrocket"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=260357&amp;type=12" width="120" height="30" alt="Get OpenRocket at SourceForge.net. Fast, secure and Free Open Source software downloads" /></a>
</div>
</div>
</div>
<h1>Support and contact information for OpenRocket</h1>
<div class="content">
<h2>Mailing lists</h2>
<p>OpenRocket currently has two mailing lists for
intrested users:</p>
<dl>
<dt>
<a href="https://lists.sourceforge.net/lists/listinfo/openrocket-announce"><tt>OpenRocket-announce</tt></a>
&nbsp;
<span class="note">(<a href="https://sourceforge.net/mailarchive/forum.php?forum_name=openrocket-announce">archives</a>)</span>
</dt>
<dd>Announcements of new OpenRocket versions and
developments. This list is moderated.</dd>
<dt>
<a href="https://lists.sourceforge.net/lists/listinfo/openrocket-devel"><tt>OpenRocket-devel</tt></a>
&nbsp;
<span class="note">(<a href="https://sourceforge.net/mailarchive/forum.php?forum_name=openrocket-devel">archives</a>)</span>
</dt>
<dd>Discussion related to OpenRocket development, documentation
and upcoming features.</dd>
</dl>
<p>You are welcome to join the development mailing list if you are
interested in contributing something to OpenRocket or simply want
hear about and discuss future development. Note that support
requests should be sent to the
<a href="http://www.rocketryforum.com/forumdisplay.php?f=36">support
forums</a> instead!</p>
<p><strong>Unsubscribing</strong> from the lists can be performed
in the above links as well. <em>Please do not send unsubscription
requests to the list.</em></p>
<h2>Support forums</h2>
<p>The official support forum for OpenRocket is the
<a href="http://www.rocketryforum.com/forumdisplay.php?f=36">Rocketry
Electronics and Software forum</a> at
<a href="http://www.rocketryforum.com/">The Rocketry Forum</a>.</p>
<p>Please ask any questions on using OpenRocket on that forum,
where others can answer as well and gain knowledge from the
answers.</p>
<h2 id="contact">Contact information</h2>
<p>The main developer of OpenRocket is Sampo Niskanen. His contact
information can be found below.</p>
<p><strong><em>Support requests</em></strong> should be sent to
the <a href="http://www.rocketryforum.com/forumdisplay.php?f=36">support
forums</a>.<br/>
<!-- <strong><em>Bug reports and feature requests</em></strong> should
be <a href="report.html">reported separately</a>.</p> -->
<p><strong>Email:</strong> &nbsp;&nbsp;
<em>sam<span>po</span>.<span>niskanen</span><span>@i</span>ki.fi</em></p>
<p><strong>WWW:</strong> &nbsp;&nbsp;
<a href="http://www.iki.fi/sampo.niskanen/"
title="Home page of Sampo Niskanen"><em>http://www.iki.fi/sampo.niskanen/</em></a></p>
</div>
<div class="valid">
<p><a href="http://validator.w3.org/check/referer"><img src="valid-xhtml10.png" alt="Valid XHTML 1.0!" /></a>
</p>
</div>
<!-- Piwik -->
<script type="text/javascript">
var pkBaseURL = (("https:" == document.location.protocol) ? "https://apps.sourceforge.net/piwik/openrocket/" : "http://apps.sourceforge.net/piwik/openrocket/");
document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
piwik_action_name = '';
piwik_idsite = 1;
piwik_url = pkBaseURL + "piwik.php";
piwik_log(piwik_action_name, piwik_idsite, piwik_url);
</script>
<noscript><p><img src="http://apps.sourceforge.net/piwik/openrocket/piwik.php?idsite=1" alt="" /></p></noscript>
<!-- End Piwik Tag -->
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>OpenRocket &mdash; Support and contact information</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="keywords" content="OpenRocket, model rocket, simulator, simulation, rocketry" />
<link rel="stylesheet" type="text/css" href="layout.css" />
<meta name="Generator" content="htp 1.18" />
</head>
<body class="page_contact">
<!--[if lte IE 6]>
<div id="iewarn">
You are using a browser that is <strong>8 years old!</strong>
&nbsp;&nbsp;&nbsp;
In Internet-years that is <em>prehistoric!</em><br/>
For the sanity of all webmasterkind,
<em>please <a href="http://www.mozilla.com/">upgrade</a></em>. It's easy!
</div>
<![endif]-->
<div class="menucontainer">
<div class="menu">
<div class="icon"><a href="index.html"></a></div>
<ul>
<li><a href="index.html">OpenRocket</a></li>
<li><a href="features.html">Features and screenshots</a></li>
<li><a href="download.html">Download</a></li>
<li><a href="documentation.html">Documentation</a></li>
<li><a href="http://wiki.openrocket.info/">Wiki pages</a></li>
<li><a href="http://openrocket.trans.free.fr/">Translations</a></li>
<li><a href="getinvolved.html">Get involved!</a></li>
<li><a href="contact.html">
Mailing lists<br/>
Support forums<br/>
Contact info</a></li>
<!--
<li><a href="report.html">
Report a bug<br/>
Request a feature</a></li>
-->
<li><a href="license.html">License</a></li>
</ul>
<div class="logo">
<a href="http://sourceforge.net/projects/openrocket"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=260357&amp;type=12" width="120" height="30" alt="Get OpenRocket at SourceForge.net. Fast, secure and Free Open Source software downloads" /></a>
</div>
</div>
</div>
<h1>Support and contact information for OpenRocket</h1>
<div class="content">
<h2>Mailing lists</h2>
<p>OpenRocket currently has two mailing lists for
intrested users:</p>
<dl>
<dt>
<a href="https://lists.sourceforge.net/lists/listinfo/openrocket-announce"><tt>OpenRocket-announce</tt></a>
&nbsp;
<span class="note">(<a href="https://sourceforge.net/mailarchive/forum.php?forum_name=openrocket-announce">archives</a>)</span>
</dt>
<dd>Announcements of new OpenRocket versions and
developments. This list is moderated.</dd>
<dt>
<a href="https://lists.sourceforge.net/lists/listinfo/openrocket-devel"><tt>OpenRocket-devel</tt></a>
&nbsp;
<span class="note">(<a href="https://sourceforge.net/mailarchive/forum.php?forum_name=openrocket-devel">archives</a>)</span>
</dt>
<dd>Discussion related to OpenRocket development, documentation
and upcoming features.</dd>
</dl>
<p>You are welcome to join the development mailing list if you are
interested in contributing something to OpenRocket or simply want
hear about and discuss future development. Note that support
requests should be sent to the
<a href="http://www.rocketryforum.com/forumdisplay.php?f=36">support
forums</a> instead!</p>
<p><strong>Unsubscribing</strong> from the lists can be performed
in the above links as well. <em>Please do not send unsubscription
requests to the list.</em></p>
<h2>Support forums</h2>
<p>The official support forum for OpenRocket is the
<a href="http://www.rocketryforum.com/forumdisplay.php?f=36">Rocketry
Electronics and Software forum</a> at
<a href="http://www.rocketryforum.com/">The Rocketry Forum</a>.</p>
<p>Please ask any questions on using OpenRocket on that forum,
where others can answer as well and gain knowledge from the
answers.</p>
<h2 id="contact">Contact information</h2>
<p>The main developer of OpenRocket is Sampo Niskanen. His contact
information can be found below.</p>
<p><strong><em>Support requests</em></strong> should be sent to
the <a href="http://www.rocketryforum.com/forumdisplay.php?f=36">support
forums</a>.<br/>
<!-- <strong><em>Bug reports and feature requests</em></strong> should
be <a href="report.html">reported separately</a>.</p> -->
<p><strong>Email:</strong> &nbsp;&nbsp;
<em>sam<span>po</span>.<span>niskanen</span><span>@i</span>ki.fi</em></p>
<p><strong>WWW:</strong> &nbsp;&nbsp;
<a href="http://www.iki.fi/sampo.niskanen/"
title="Home page of Sampo Niskanen"><em>http://www.iki.fi/sampo.niskanen/</em></a></p>
</div>
<div class="valid">
<p><a href="http://validator.w3.org/check/referer"><img src="valid-xhtml10.png" alt="Valid XHTML 1.0!" /></a>
</p>
</div>
<!-- Piwik -->
<script type="text/javascript">
var pkBaseURL = (("https:" == document.location.protocol) ? "https://apps.sourceforge.net/piwik/openrocket/" : "http://apps.sourceforge.net/piwik/openrocket/");
document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
piwik_action_name = '';
piwik_idsite = 1;
piwik_url = pkBaseURL + "piwik.php";
piwik_log(piwik_action_name, piwik_idsite, piwik_url);
</script>
<noscript><p><img src="http://apps.sourceforge.net/piwik/openrocket/piwik.php?idsite=1" alt="" /></p></noscript>
<!-- End Piwik Tag -->
</body>
</html>

@ -1,122 +1,122 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>OpenRocket &mdash; Documentation</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="keywords" content="OpenRocket, model rocket, simulator, simulation, rocketry" />
<link rel="stylesheet" type="text/css" href="layout.css" />
<meta name="Generator" content="htp 1.18" />
</head>
<body class="page_documentation">
<!--[if lte IE 6]>
<div id="iewarn">
You are using a browser that is <strong>8 years old!</strong>
&nbsp;&nbsp;&nbsp;
In Internet-years that is <em>prehistoric!</em><br/>
For the sanity of all webmasterkind,
<em>please <a href="http://www.mozilla.com/">upgrade</a></em>. It's easy!
</div>
<![endif]-->
<div class="menucontainer">
<div class="menu">
<div class="icon"><a href="index.html"></a></div>
<ul>
<li><a href="index.html">OpenRocket</a></li>
<li><a href="features.html">Features and screenshots</a></li>
<li><a href="download.html">Download</a></li>
<li><a href="documentation.html">Documentation</a></li>
<li><a href="http://wiki.openrocket.info/">Wiki pages</a></li>
<li><a href="http://openrocket.trans.free.fr/">Translations</a></li>
<li><a href="getinvolved.html">Get involved!</a></li>
<li><a href="contact.html">
Mailing lists<br/>
Support forums<br/>
Contact info</a></li>
<!--
<li><a href="report.html">
Report a bug<br/>
Request a feature</a></li>
-->
<li><a href="license.html">License</a></li>
</ul>
<div class="logo">
<a href="http://sourceforge.net/projects/openrocket"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=260357&amp;type=12" width="120" height="30" alt="Get OpenRocket at SourceForge.net. Fast, secure and Free Open Source software downloads" /></a>
</div>
</div>
</div>
<h1>Documentation for OpenRocket</h1>
<div class="content">
<h2>User documentation</h2>
<p>Unfortunately no user's guide currently exists for OpenRocket.
Some documentation is available in the
<a href="http://wiki.openrocket.info/">OpenRocket
wiki pages</a>, including a stub
<a href="http://wiki.openrocket.info/User%27s_Guide">User's
guide</a> and a section of
<a href="http://wiki.openrocket.info/FAQ">frequently
asked questions</a>.</p>
<p>If you would like to help, please extend the documentation!</p>
<h2>Technical documentation</h2>
<p>OpenRocket was originally written as the Master's thesis of
Sampo Niskanen at Helsinki University of Technology. This thesis
is being extended and updated as the OpenRocket technical
documentation. Below is the latest technical documentation and
the original Master's thesis.</p>
<div class="separated">
<p>
<span class="licenseimage"><a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="CC BY-SA" src="cc-by-sa-80x15.png" /></a></span>
<a href="techdoc.pdf">OpenRocket technical documentation</a> (2013-05-10)
&nbsp;&nbsp; <span class="note">(PDF&nbsp;1.4MB)</span>
</p>
<p>
<span class="licenseimage"><a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/3.0/"><img alt="CC BY-NC-ND" src="cc-by-nc-nd-80x15.png" /></a></span>
<a href="thesis.pdf">Development of an Open Source model rocket simulation software</a> (Master's thesis)
&nbsp;&nbsp; <span class="note">(PDF&nbsp;1.3MB)</span>
</p>
</div>
<p>The technical documentation is licensed under a
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike License</a>
while the Master's thesis is licensed under a
<a rel="license" href="http://creativecommons.org/licenses/by-nd-nc/1.0/fi/deed.en">Attribution-NonCommercial-NoDerivs
License</a>.
</p>
<p class="quote"><strong>Table of contents:</strong></p>
<ol class="toc">
<li>1. Introduction</li>
<li>2. Basics of model rocket flight</li>
<li>3. Aerodynamic properties of model rockets</li>
<li>4. Flight simulation</li>
<li>5. The OpenRocket simulation software</li>
<li>6. Comparison with experimental data</li>
<li>7. Conclusion</li>
</ol>
<ol class="toc">
<li>A. Nose cone and transition geometries</li>
<li>B. Transonic wave drag of nose cones</li>
<li>C. Streamer drag coefficient estimation</li>
</ol>
<h2>Resources</h2>
<p>A list of useful technical rocketry resources is available in
the <a href="http://wiki.openrocket.info/Resources">"Resources"
wiki page</a>, including links to Barrowman's original report and
thesis, extensions for the Barrowman method, experimental rocket
data etc.</p>
</div>
<div class="valid">
<p><a href="http://validator.w3.org/check/referer"><img src="valid-xhtml10.png" alt="Valid XHTML 1.0!" /></a>
</p>
</div>
<!-- Piwik -->
<script type="text/javascript">
var pkBaseURL = (("https:" == document.location.protocol) ? "https://apps.sourceforge.net/piwik/openrocket/" : "http://apps.sourceforge.net/piwik/openrocket/");
document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
piwik_action_name = '';
piwik_idsite = 1;
piwik_url = pkBaseURL + "piwik.php";
piwik_log(piwik_action_name, piwik_idsite, piwik_url);
</script>
<noscript><p><img src="http://apps.sourceforge.net/piwik/openrocket/piwik.php?idsite=1" alt="" /></p></noscript>
<!-- End Piwik Tag -->
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>OpenRocket &mdash; Documentation</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="keywords" content="OpenRocket, model rocket, simulator, simulation, rocketry" />
<link rel="stylesheet" type="text/css" href="layout.css" />
<meta name="Generator" content="htp 1.18" />
</head>
<body class="page_documentation">
<!--[if lte IE 6]>
<div id="iewarn">
You are using a browser that is <strong>8 years old!</strong>
&nbsp;&nbsp;&nbsp;
In Internet-years that is <em>prehistoric!</em><br/>
For the sanity of all webmasterkind,
<em>please <a href="http://www.mozilla.com/">upgrade</a></em>. It's easy!
</div>
<![endif]-->
<div class="menucontainer">
<div class="menu">
<div class="icon"><a href="index.html"></a></div>
<ul>
<li><a href="index.html">OpenRocket</a></li>
<li><a href="features.html">Features and screenshots</a></li>
<li><a href="download.html">Download</a></li>
<li><a href="documentation.html">Documentation</a></li>
<li><a href="http://wiki.openrocket.info/">Wiki pages</a></li>
<li><a href="http://openrocket.trans.free.fr/">Translations</a></li>
<li><a href="getinvolved.html">Get involved!</a></li>
<li><a href="contact.html">
Mailing lists<br/>
Support forums<br/>
Contact info</a></li>
<!--
<li><a href="report.html">
Report a bug<br/>
Request a feature</a></li>
-->
<li><a href="license.html">License</a></li>
</ul>
<div class="logo">
<a href="http://sourceforge.net/projects/openrocket"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=260357&amp;type=12" width="120" height="30" alt="Get OpenRocket at SourceForge.net. Fast, secure and Free Open Source software downloads" /></a>
</div>
</div>
</div>
<h1>Documentation for OpenRocket</h1>
<div class="content">
<h2>User documentation</h2>
<p>Unfortunately no user's guide currently exists for OpenRocket.
Some documentation is available in the
<a href="http://wiki.openrocket.info/">OpenRocket
wiki pages</a>, including a stub
<a href="http://wiki.openrocket.info/User%27s_Guide">User's
guide</a> and a section of
<a href="http://wiki.openrocket.info/FAQ">frequently
asked questions</a>.</p>
<p>If you would like to help, please extend the documentation!</p>
<h2>Technical documentation</h2>
<p>OpenRocket was originally written as the Master's thesis of
Sampo Niskanen at Helsinki University of Technology. This thesis
is being extended and updated as the OpenRocket technical
documentation. Below is the latest technical documentation and
the original Master's thesis.</p>
<div class="separated">
<p>
<span class="licenseimage"><a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="CC BY-SA" src="cc-by-sa-80x15.png" /></a></span>
<a href="techdoc.pdf">OpenRocket technical documentation</a> (2013-05-10)
&nbsp;&nbsp; <span class="note">(PDF&nbsp;1.4MB)</span>
</p>
<p>
<span class="licenseimage"><a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/3.0/"><img alt="CC BY-NC-ND" src="cc-by-nc-nd-80x15.png" /></a></span>
<a href="thesis.pdf">Development of an Open Source model rocket simulation software</a> (Master's thesis)
&nbsp;&nbsp; <span class="note">(PDF&nbsp;1.3MB)</span>
</p>
</div>
<p>The technical documentation is licensed under a
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike License</a>
while the Master's thesis is licensed under a
<a rel="license" href="http://creativecommons.org/licenses/by-nd-nc/1.0/fi/deed.en">Attribution-NonCommercial-NoDerivs
License</a>.
</p>
<p class="quote"><strong>Table of contents:</strong></p>
<ol class="toc">
<li>1. Introduction</li>
<li>2. Basics of model rocket flight</li>
<li>3. Aerodynamic properties of model rockets</li>
<li>4. Flight simulation</li>
<li>5. The OpenRocket simulation software</li>
<li>6. Comparison with experimental data</li>
<li>7. Conclusion</li>
</ol>
<ol class="toc">
<li>A. Nose cone and transition geometries</li>
<li>B. Transonic wave drag of nose cones</li>
<li>C. Streamer drag coefficient estimation</li>
</ol>
<h2>Resources</h2>
<p>A list of useful technical rocketry resources is available in
the <a href="http://wiki.openrocket.info/Resources">"Resources"
wiki page</a>, including links to Barrowman's original report and
thesis, extensions for the Barrowman method, experimental rocket
data etc.</p>
</div>
<div class="valid">
<p><a href="http://validator.w3.org/check/referer"><img src="valid-xhtml10.png" alt="Valid XHTML 1.0!" /></a>
</p>
</div>
<!-- Piwik -->
<script type="text/javascript">
var pkBaseURL = (("https:" == document.location.protocol) ? "https://apps.sourceforge.net/piwik/openrocket/" : "http://apps.sourceforge.net/piwik/openrocket/");
document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
piwik_action_name = '';
piwik_idsite = 1;
piwik_url = pkBaseURL + "piwik.php";
piwik_log(piwik_action_name, piwik_idsite, piwik_url);
</script>
<noscript><p><img src="http://apps.sourceforge.net/piwik/openrocket/piwik.php?idsite=1" alt="" /></p></noscript>
<!-- End Piwik Tag -->
</body>
</html>

@ -1,156 +1,156 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>OpenRocket &mdash; Download</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="keywords" content="OpenRocket, model rocket, simulator, simulation, rocketry" />
<link rel="stylesheet" type="text/css" href="layout.css" />
<meta name="Generator" content="htp 1.18" />
</head>
<body class="page_download">
<!--[if lte IE 6]>
<div id="iewarn">
You are using a browser that is <strong>8 years old!</strong>
&nbsp;&nbsp;&nbsp;
In Internet-years that is <em>prehistoric!</em><br/>
For the sanity of all webmasterkind,
<em>please <a href="http://www.mozilla.com/">upgrade</a></em>. It's easy!
</div>
<![endif]-->
<div class="menucontainer">
<div class="menu">
<div class="icon"><a href="index.html"></a></div>
<ul>
<li><a href="index.html">OpenRocket</a></li>
<li><a href="features.html">Features and screenshots</a></li>
<li><a href="download.html">Download</a></li>
<li><a href="documentation.html">Documentation</a></li>
<li><a href="http://wiki.openrocket.info/">Wiki pages</a></li>
<li><a href="http://openrocket.trans.free.fr/">Translations</a></li>
<li><a href="getinvolved.html">Get involved!</a></li>
<li><a href="contact.html">
Mailing lists<br/>
Support forums<br/>
Contact info</a></li>
<!--
<li><a href="report.html">
Report a bug<br/>
Request a feature</a></li>
-->
<li><a href="license.html">License</a></li>
</ul>
<div class="logo">
<a href="http://sourceforge.net/projects/openrocket"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=260357&amp;type=12" width="120" height="30" alt="Get OpenRocket at SourceForge.net. Fast, secure and Free Open Source software downloads" /></a>
</div>
</div>
</div>
<h1>Download OpenRocket</h1>
<div class="content">
<div class="news">
<h2>Recent news:</h2>
<p><span class="date">28.03.2015:</span> Version 15.03 is
<a href="download.html">released</a>! This release contains scriptable simulation extensions and experimental support for tube fins along with many additional improvements.
</p>
<p><span class="date">02.11.2014:</span> Version 14.11 is
<a href="download.html">released</a>! This release contains very few changes. Thrustcurves have been updated and now include AeroTech DMS motors. A few bugs have been fixed.
</p>
<p><span class="date">25.06.2014:</span> Version 14.06 is
<a href="download.html">released</a>! This release contains very minimal changes. It fixes an annoying bug in tables that many people experience. A texture is added for Klima motors.
</p>
<p><span class="date">21.05.2014:</span> Version 14.05 is
<a href="download.html">released</a>! This release contains some minor features,
bug fixes and updated thrust curves. New motor vendors Klima and Southern
Cross Rocketry are included. The simulation will now compute optimum delay based
on actual coast time. Components with CG and mass overrides are decorated with
an icon in the component tree.
</p>
<p><span class="date">21.03.2014:</span> Version 14.03 is
<a href="download.html">released</a>! This release contains the
new photo realistic renderer (in the Tools menu) which allows one to visualize
the rocket in the air. There are various bug fixes in the configuration
and motor selection windows as well.
</p>
</div>
<div class="contentholder">
<h2>Ready packages</h2>
<p>These are packages ready for use and are the recommended
download for normal users. They are pre-packaged with motor
thrust curves from
<a href="http://www.thrustcurve.org/">thrustcurve.org</a>.</p>
<p>OpenRocket requires <strong>Java version 6</strong> or
later. The Sun Java Runtime is recommended.</p>
<h3>Desktop version</h3>
<p>This is the latest version of the desktop version of
OpenRocket. It contains the latest and greatest features, and
runs on any system supporting Java.</p>
<div class="left">
<img src="java_logo.png" alt="" />
</div>
<div class="right support">
<a href="http://sourceforge.net/donate/index.php?group_id=260357"><img src="project-support.jpg" width="88" height="32" alt="Support This Project" /></a>
</div>
<div class="downloadbox">
<a class="main" href="https://sourceforge.net/projects/openrocket/files/openrocket/15.03/OpenRocket-15.03.jar/download">
<strong>Download now!</strong>
<span>OpenRocket-15.03.jar</span>
</a>
<span class="alternative">
<a href="https://sourceforge.net/projects/openrocket/files/openrocket/15.03/ReleaseNotes/view">Release notes</a> |
<a href="https://sourceforge.net/projects/openrocket/files/openrocket/15.03/OpenRocket-15.03-src.zip/download">Source code</a>
</span>
</div>
<p>OpenRocket can be started in most graphical environments (including
Windows) by double-clicking the package icon. No installation is
required.</p>
<p>From the command line OpenRocket can be started by
<span class="command">java -jar OpenRocket-15.03.jar</span></p>
<h3>Android version</h3>
<p>The Android version allows opening OpenRocket files, viewing
simulations and motors. Later versions will allow running
simulations as well.</p>
<p>The Android version is thanks to the fantastic work by Kevin
Ruland.</p>
<div class="left">
<img src="android_logo.png" alt="" />
</div>
<div class="instructions">
<p>Installation:</p>
<ol>
<li>Go to <em>Settings</em> &rarr; <em>Applications</em> and
check <em>Unknown sources</em>.</li>
<li>Download <a href="https://sourceforge.net/projects/openrocket/files/openrocket/13.11/OpenRocket-Android-13.11.apk/download">OpenRocket-Android-13.11.apk</a>
on your device and accept installation.</li>
</ol>
</div>
</div>
<div class="clear"></div>
<h2>Source code and older versions</h2>
<p><strong>Source packages</strong> and older versions of
OpenRocket are available in the
<a href="https://sourceforge.net/projects/openrocket/files/openrocket/">SourceForge repository</a>.</p>
<p>Alternatively, the most recent development version can be
obtained from
<a href="https://github.com/openrocket/openrocket/">GitHub</a>.
The code can be retrieved using the command</p>
<pre class="quote">$ git clone git://github.com/openrocket/openrocket.git</pre>
<p>The above URL may be used to connect to the repository with
other Git clients as well.</p>
</div>
<div class="valid">
<p><a href="http://validator.w3.org/check/referer"><img src="valid-xhtml10.png" alt="Valid XHTML 1.0!" /></a>
</p>
</div>
<!-- Piwik -->
<script type="text/javascript">
var pkBaseURL = (("https:" == document.location.protocol) ? "https://apps.sourceforge.net/piwik/openrocket/" : "http://apps.sourceforge.net/piwik/openrocket/");
document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
piwik_action_name = '';
piwik_idsite = 1;
piwik_url = pkBaseURL + "piwik.php";
piwik_log(piwik_action_name, piwik_idsite, piwik_url);
</script>
<noscript><p><img src="http://apps.sourceforge.net/piwik/openrocket/piwik.php?idsite=1" alt="" /></p></noscript>
<!-- End Piwik Tag -->
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>OpenRocket &mdash; Download</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="keywords" content="OpenRocket, model rocket, simulator, simulation, rocketry" />
<link rel="stylesheet" type="text/css" href="layout.css" />
<meta name="Generator" content="htp 1.18" />
</head>
<body class="page_download">
<!--[if lte IE 6]>
<div id="iewarn">
You are using a browser that is <strong>8 years old!</strong>
&nbsp;&nbsp;&nbsp;
In Internet-years that is <em>prehistoric!</em><br/>
For the sanity of all webmasterkind,
<em>please <a href="http://www.mozilla.com/">upgrade</a></em>. It's easy!
</div>
<![endif]-->
<div class="menucontainer">
<div class="menu">
<div class="icon"><a href="index.html"></a></div>
<ul>
<li><a href="index.html">OpenRocket</a></li>
<li><a href="features.html">Features and screenshots</a></li>
<li><a href="download.html">Download</a></li>
<li><a href="documentation.html">Documentation</a></li>
<li><a href="http://wiki.openrocket.info/">Wiki pages</a></li>
<li><a href="http://openrocket.trans.free.fr/">Translations</a></li>
<li><a href="getinvolved.html">Get involved!</a></li>
<li><a href="contact.html">
Mailing lists<br/>
Support forums<br/>
Contact info</a></li>
<!--
<li><a href="report.html">
Report a bug<br/>
Request a feature</a></li>
-->
<li><a href="license.html">License</a></li>
</ul>
<div class="logo">
<a href="http://sourceforge.net/projects/openrocket"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=260357&amp;type=12" width="120" height="30" alt="Get OpenRocket at SourceForge.net. Fast, secure and Free Open Source software downloads" /></a>
</div>
</div>
</div>
<h1>Download OpenRocket</h1>
<div class="content">
<div class="news">
<h2>Recent news:</h2>
<p><span class="date">28.03.2015:</span> Version 15.03 is
<a href="download.html">released</a>! This release contains scriptable simulation extensions and experimental support for tube fins along with many additional improvements.
</p>
<p><span class="date">02.11.2014:</span> Version 14.11 is
<a href="download.html">released</a>! This release contains very few changes. Thrustcurves have been updated and now include AeroTech DMS motors. A few bugs have been fixed.
</p>
<p><span class="date">25.06.2014:</span> Version 14.06 is
<a href="download.html">released</a>! This release contains very minimal changes. It fixes an annoying bug in tables that many people experience. A texture is added for Klima motors.
</p>
<p><span class="date">21.05.2014:</span> Version 14.05 is
<a href="download.html">released</a>! This release contains some minor features,
bug fixes and updated thrust curves. New motor vendors Klima and Southern
Cross Rocketry are included. The simulation will now compute optimum delay based
on actual coast time. Components with CG and mass overrides are decorated with
an icon in the component tree.
</p>
<p><span class="date">21.03.2014:</span> Version 14.03 is
<a href="download.html">released</a>! This release contains the
new photo realistic renderer (in the Tools menu) which allows one to visualize
the rocket in the air. There are various bug fixes in the configuration
and motor selection windows as well.
</p>
</div>
<div class="contentholder">
<h2>Ready packages</h2>
<p>These are packages ready for use and are the recommended
download for normal users. They are pre-packaged with motor
thrust curves from
<a href="http://www.thrustcurve.org/">thrustcurve.org</a>.</p>
<p>OpenRocket requires <strong>Java version 6</strong> or
later. The Sun Java Runtime is recommended.</p>
<h3>Desktop version</h3>
<p>This is the latest version of the desktop version of
OpenRocket. It contains the latest and greatest features, and
runs on any system supporting Java.</p>
<div class="left">
<img src="java_logo.png" alt="" />
</div>
<div class="right support">
<a href="http://sourceforge.net/donate/index.php?group_id=260357"><img src="project-support.jpg" width="88" height="32" alt="Support This Project" /></a>
</div>
<div class="downloadbox">
<a class="main" href="https://sourceforge.net/projects/openrocket/files/openrocket/15.03/OpenRocket-15.03.jar/download">
<strong>Download now!</strong>
<span>OpenRocket-15.03.jar</span>
</a>
<span class="alternative">
<a href="https://sourceforge.net/projects/openrocket/files/openrocket/15.03/ReleaseNotes/view">Release notes</a> |
<a href="https://sourceforge.net/projects/openrocket/files/openrocket/15.03/OpenRocket-15.03-src.zip/download">Source code</a>
</span>
</div>
<p>OpenRocket can be started in most graphical environments (including
Windows) by double-clicking the package icon. No installation is
required.</p>
<p>From the command line OpenRocket can be started by
<span class="command">java -jar OpenRocket-15.03.jar</span></p>
<h3>Android version</h3>
<p>The Android version allows opening OpenRocket files, viewing
simulations and motors. Later versions will allow running
simulations as well.</p>
<p>The Android version is thanks to the fantastic work by Kevin
Ruland.</p>
<div class="left">
<img src="android_logo.png" alt="" />
</div>
<div class="instructions">
<p>Installation:</p>
<ol>
<li>Go to <em>Settings</em> &rarr; <em>Applications</em> and
check <em>Unknown sources</em>.</li>
<li>Download <a href="https://sourceforge.net/projects/openrocket/files/openrocket/13.11/OpenRocket-Android-13.11.apk/download">OpenRocket-Android-13.11.apk</a>
on your device and accept installation.</li>
</ol>
</div>
</div>
<div class="clear"></div>
<h2>Source code and older versions</h2>
<p><strong>Source packages</strong> and older versions of
OpenRocket are available in the
<a href="https://sourceforge.net/projects/openrocket/files/openrocket/">SourceForge repository</a>.</p>
<p>Alternatively, the most recent development version can be
obtained from
<a href="https://github.com/openrocket/openrocket/">GitHub</a>.
The code can be retrieved using the command</p>
<pre class="quote">$ git clone git://github.com/openrocket/openrocket.git</pre>
<p>The above URL may be used to connect to the repository with
other Git clients as well.</p>
</div>
<div class="valid">
<p><a href="http://validator.w3.org/check/referer"><img src="valid-xhtml10.png" alt="Valid XHTML 1.0!" /></a>
</p>
</div>
<!-- Piwik -->
<script type="text/javascript">
var pkBaseURL = (("https:" == document.location.protocol) ? "https://apps.sourceforge.net/piwik/openrocket/" : "http://apps.sourceforge.net/piwik/openrocket/");
document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
piwik_action_name = '';
piwik_idsite = 1;
piwik_url = pkBaseURL + "piwik.php";
piwik_log(piwik_action_name, piwik_idsite, piwik_url);
</script>
<noscript><p><img src="http://apps.sourceforge.net/piwik/openrocket/piwik.php?idsite=1" alt="" /></p></noscript>
<!-- End Piwik Tag -->
</body>
</html>

@ -1,181 +1,181 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>OpenRocket &mdash; Features and screenshots</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="keywords" content="OpenRocket, model rocket, simulator, simulation, rocketry" />
<link rel="stylesheet" type="text/css" href="layout.css" />
<meta name="Generator" content="htp 1.18" />
</head>
<body class="page_features">
<!--[if lte IE 6]>
<div id="iewarn">
You are using a browser that is <strong>8 years old!</strong>
&nbsp;&nbsp;&nbsp;
In Internet-years that is <em>prehistoric!</em><br/>
For the sanity of all webmasterkind,
<em>please <a href="http://www.mozilla.com/">upgrade</a></em>. It's easy!
</div>
<![endif]-->
<div class="menucontainer">
<div class="menu">
<div class="icon"><a href="index.html"></a></div>
<ul>
<li><a href="index.html">OpenRocket</a></li>
<li><a href="features.html">Features and screenshots</a></li>
<li><a href="download.html">Download</a></li>
<li><a href="documentation.html">Documentation</a></li>
<li><a href="http://wiki.openrocket.info/">Wiki pages</a></li>
<li><a href="http://openrocket.trans.free.fr/">Translations</a></li>
<li><a href="getinvolved.html">Get involved!</a></li>
<li><a href="contact.html">
Mailing lists<br/>
Support forums<br/>
Contact info</a></li>
<!--
<li><a href="report.html">
Report a bug<br/>
Request a feature</a></li>
-->
<li><a href="license.html">License</a></li>
</ul>
<div class="logo">
<a href="http://sourceforge.net/projects/openrocket"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=260357&amp;type=12" width="120" height="30" alt="Get OpenRocket at SourceForge.net. Fast, secure and Free Open Source software downloads" /></a>
</div>
</div>
</div>
<h1>Features of OpenRocket</h1>
<div class="content">
<h2>Current features</h2>
<div class="screenshots">
<div class="smallshotconst"><a href="shots/main.png">
<img src="shots-small/main.jpg" alt="Main window" /><br/>
The main rocket design window is used to design the rocket
and it also provides information about a flight simulation
in real-time.
</a></div>
<div class="smallshotconst"><a href="shots/dart.png">
<img src="shots-small/dart.jpg" alt="Realistic 3D Rendering" /><br/>
Paint and decals can be added and rendered in 3D.
</a></div>
<div class="smallshotconst"><a href="shots/dialog-edit.png">
<img src="shots-small/dialog-edit.jpg" alt="Component edit
dialog" /><br/>
The component shape and properties are defined in their own
dialog.
</a></div>
<div class="smallshotconst"><a href="shots/dialog-analysis.png">
<img src="shots-small/dialog-analysis.jpg" alt="Analysis
dialog" /><br/>
You can analyze the effect of individual components on the
stability, drag and roll characteristics of the rocket.
</a></div>
<div class="smallshotconst"><a href="shots/dialog-plot-options.png">
<img src="shots-small/dialog-plot-options.jpg"
alt="Simulation plot options" /><br/>
The simulation results can be plotted in a multitude
of ways. You can either use the predefined plot
configurations or define your own.<br/>
</a></div>
<div class="smallshotconst"><a href="shots/dialog-plot.png">
<img src="shots-small/dialog-plot.jpg" alt="Simulation plot" /><br/>
The simulations are plotted using the
<em>JFreeChart</em> plotting library.
</a></div>
</div>
<h3>General</h3>
<ul>
<li><strong>Fully cross-platform</strong>, written in Java</li>
<li><strong>Fully documented</strong> <a href="documentation.html">simulation
methods</a></li>
<li><strong>Open Source</strong>, source code available under the
<a href="license.html">GNU GPL</a></li>
</ul>
<h3>User interface</h3>
<ul>
<li><strong>Easy-to-use user interface</strong> for
rocket design</li>
<li><strong>Real-time view of CG and CP</strong> position</li>
<li><strong>Real-time flight altitude, velocity and
acceleration</strong> information from a continuous simulation
performed in the background</li>
<li>Zoomable schematic view of rocket from the side or rear,
with rotation around the center axis</li>
</ul>
<h3>Design</h3>
<ul>
<li>A multitude of available components to
choose from</li>
<li><strong>Trapezoidal</strong>, <strong>elliptical</strong>
and <strong>free-form fins</strong> supported</li>
<li>Support for <strong>canted fins</strong> (roll
stabilization)</li>
<li><strong>Staging</strong> and <strong>clustering</strong> support</li>
<li>Automatic calculation of component mass and CG based on
shape and density</li>
<li>Ability to <strong>override mass and CG</strong> of
components or stages separately</li>
</ul>
<h3>Simulation and analysis</h3>
<ul>
<li>Full <strong>six degree of freedom</strong> simulation</li>
<li>Rocket stability computed using <strong>extended Barrowman
method</strong></li>
<li><strong>Automatic design optimization</strong> &mdash; you
can optimize any number of rocket parameters for flight
altitude, maximum velocity or a number of other values</li>
<li>Realistic wind modeling</li>
<li>Analysis of the <strong>effect of separate
components</strong> on the stability, drag and roll
characteristics of the rocket</li>
<li><strong>Fully configurable plotting</strong>, with
various preset configurations</li>
<li>Simulation data can be <strong>exported to
<acronym title="Comma Separated Values">CSV</acronym>
files</strong> for further analysis</li>
<li><strong>Simulation listeners</strong> allowing custom-made
code to interact with the rocket during flight simulation</li>
</ul>
<h2 id="future">Planned future features</h2>
<p>OpenRocket is under constant work in the free time of the
developers. You can have a sneak preview on what has been
planned by checking the
<a href="https://raw.github.com/openrocket/openrocket/master/core/TODO">TODO-file</a>
on github.</p>
<p>Below are a few major features that are under consideration:</p>
<ul>
<li>Aerodynamic computation using
<acronym title="Computational Fluid Dynamics">CFD</acronym>
<a href="getinvolved.html" class="help">(help needed!)</a></li>
<li>Better support for supersonic simulation
<a href="getinvolved.html" class="help">(help needed!)</a></li>
<li>Customized support for hybrid rocket motors and water
rockets</li>
<li>Importing and plotting actual flight data from altimeters</li>
<li>Rocket flight animation</li>
<li>A "wizard" for creating new rocket designs</li>
<li class="spacer">More ideas are listed in the
<a href="https://raw.github.com/openrocket/openrocket/master/core/TODO">TODO-file</a>!</li>
</ul>
<p>If you want to help make OpenRocket the best rocket simulator,
don't hesitate to <a href="getinvolved.html">Get involved!</a></p>
<div class="clear"></div>
</div>
<div class="valid">
<p><a href="http://validator.w3.org/check/referer"><img src="valid-xhtml10.png" alt="Valid XHTML 1.0!" /></a>
</p>
</div>
<!-- Piwik -->
<script type="text/javascript">
var pkBaseURL = (("https:" == document.location.protocol) ? "https://apps.sourceforge.net/piwik/openrocket/" : "http://apps.sourceforge.net/piwik/openrocket/");
document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
piwik_action_name = '';
piwik_idsite = 1;
piwik_url = pkBaseURL + "piwik.php";
piwik_log(piwik_action_name, piwik_idsite, piwik_url);
</script>
<noscript><p><img src="http://apps.sourceforge.net/piwik/openrocket/piwik.php?idsite=1" alt="" /></p></noscript>
<!-- End Piwik Tag -->
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>OpenRocket &mdash; Features and screenshots</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="keywords" content="OpenRocket, model rocket, simulator, simulation, rocketry" />
<link rel="stylesheet" type="text/css" href="layout.css" />
<meta name="Generator" content="htp 1.18" />
</head>
<body class="page_features">
<!--[if lte IE 6]>
<div id="iewarn">
You are using a browser that is <strong>8 years old!</strong>
&nbsp;&nbsp;&nbsp;
In Internet-years that is <em>prehistoric!</em><br/>
For the sanity of all webmasterkind,
<em>please <a href="http://www.mozilla.com/">upgrade</a></em>. It's easy!
</div>
<![endif]-->
<div class="menucontainer">
<div class="menu">
<div class="icon"><a href="index.html"></a></div>
<ul>
<li><a href="index.html">OpenRocket</a></li>
<li><a href="features.html">Features and screenshots</a></li>
<li><a href="download.html">Download</a></li>
<li><a href="documentation.html">Documentation</a></li>
<li><a href="http://wiki.openrocket.info/">Wiki pages</a></li>
<li><a href="http://openrocket.trans.free.fr/">Translations</a></li>
<li><a href="getinvolved.html">Get involved!</a></li>
<li><a href="contact.html">
Mailing lists<br/>
Support forums<br/>
Contact info</a></li>
<!--
<li><a href="report.html">
Report a bug<br/>
Request a feature</a></li>
-->
<li><a href="license.html">License</a></li>
</ul>
<div class="logo">
<a href="http://sourceforge.net/projects/openrocket"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=260357&amp;type=12" width="120" height="30" alt="Get OpenRocket at SourceForge.net. Fast, secure and Free Open Source software downloads" /></a>
</div>
</div>
</div>
<h1>Features of OpenRocket</h1>
<div class="content">
<h2>Current features</h2>
<div class="screenshots">
<div class="smallshotconst"><a href="shots/main.png">
<img src="shots-small/main.jpg" alt="Main window" /><br/>
The main rocket design window is used to design the rocket
and it also provides information about a flight simulation
in real-time.
</a></div>
<div class="smallshotconst"><a href="shots/dart.png">
<img src="shots-small/dart.jpg" alt="Realistic 3D Rendering" /><br/>
Paint and decals can be added and rendered in 3D.
</a></div>
<div class="smallshotconst"><a href="shots/dialog-edit.png">
<img src="shots-small/dialog-edit.jpg" alt="Component edit
dialog" /><br/>
The component shape and properties are defined in their own
dialog.
</a></div>
<div class="smallshotconst"><a href="shots/dialog-analysis.png">
<img src="shots-small/dialog-analysis.jpg" alt="Analysis
dialog" /><br/>
You can analyze the effect of individual components on the
stability, drag and roll characteristics of the rocket.
</a></div>
<div class="smallshotconst"><a href="shots/dialog-plot-options.png">
<img src="shots-small/dialog-plot-options.jpg"
alt="Simulation plot options" /><br/>
The simulation results can be plotted in a multitude
of ways. You can either use the predefined plot
configurations or define your own.<br/>
</a></div>
<div class="smallshotconst"><a href="shots/dialog-plot.png">
<img src="shots-small/dialog-plot.jpg" alt="Simulation plot" /><br/>
The simulations are plotted using the
<em>JFreeChart</em> plotting library.
</a></div>
</div>
<h3>General</h3>
<ul>
<li><strong>Fully cross-platform</strong>, written in Java</li>
<li><strong>Fully documented</strong> <a href="documentation.html">simulation
methods</a></li>
<li><strong>Open Source</strong>, source code available under the
<a href="license.html">GNU GPL</a></li>
</ul>
<h3>User interface</h3>
<ul>
<li><strong>Easy-to-use user interface</strong> for
rocket design</li>
<li><strong>Real-time view of CG and CP</strong> position</li>
<li><strong>Real-time flight altitude, velocity and
acceleration</strong> information from a continuous simulation
performed in the background</li>
<li>Zoomable schematic view of rocket from the side or rear,
with rotation around the center axis</li>
</ul>
<h3>Design</h3>
<ul>
<li>A multitude of available components to
choose from</li>
<li><strong>Trapezoidal</strong>, <strong>elliptical</strong>
and <strong>free-form fins</strong> supported</li>
<li>Support for <strong>canted fins</strong> (roll
stabilization)</li>
<li><strong>Staging</strong> and <strong>clustering</strong> support</li>
<li>Automatic calculation of component mass and CG based on
shape and density</li>
<li>Ability to <strong>override mass and CG</strong> of
components or stages separately</li>
</ul>
<h3>Simulation and analysis</h3>
<ul>
<li>Full <strong>six degree of freedom</strong> simulation</li>
<li>Rocket stability computed using <strong>extended Barrowman
method</strong></li>
<li><strong>Automatic design optimization</strong> &mdash; you
can optimize any number of rocket parameters for flight
altitude, maximum velocity or a number of other values</li>
<li>Realistic wind modeling</li>
<li>Analysis of the <strong>effect of separate
components</strong> on the stability, drag and roll
characteristics of the rocket</li>
<li><strong>Fully configurable plotting</strong>, with
various preset configurations</li>
<li>Simulation data can be <strong>exported to
<acronym title="Comma Separated Values">CSV</acronym>
files</strong> for further analysis</li>
<li><strong>Simulation listeners</strong> allowing custom-made
code to interact with the rocket during flight simulation</li>
</ul>
<h2 id="future">Planned future features</h2>
<p>OpenRocket is under constant work in the free time of the
developers. You can have a sneak preview on what has been
planned by checking the
<a href="https://raw.github.com/openrocket/openrocket/master/core/TODO">TODO-file</a>
on github.</p>
<p>Below are a few major features that are under consideration:</p>
<ul>
<li>Aerodynamic computation using
<acronym title="Computational Fluid Dynamics">CFD</acronym>
<a href="getinvolved.html" class="help">(help needed!)</a></li>
<li>Better support for supersonic simulation
<a href="getinvolved.html" class="help">(help needed!)</a></li>
<li>Customized support for hybrid rocket motors and water
rockets</li>
<li>Importing and plotting actual flight data from altimeters</li>
<li>Rocket flight animation</li>
<li>A "wizard" for creating new rocket designs</li>
<li class="spacer">More ideas are listed in the
<a href="https://raw.github.com/openrocket/openrocket/master/core/TODO">TODO-file</a>!</li>
</ul>
<p>If you want to help make OpenRocket the best rocket simulator,
don't hesitate to <a href="getinvolved.html">Get involved!</a></p>
<div class="clear"></div>
</div>
<div class="valid">
<p><a href="http://validator.w3.org/check/referer"><img src="valid-xhtml10.png" alt="Valid XHTML 1.0!" /></a>
</p>
</div>
<!-- Piwik -->
<script type="text/javascript">
var pkBaseURL = (("https:" == document.location.protocol) ? "https://apps.sourceforge.net/piwik/openrocket/" : "http://apps.sourceforge.net/piwik/openrocket/");
document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
piwik_action_name = '';
piwik_idsite = 1;
piwik_url = pkBaseURL + "piwik.php";
piwik_log(piwik_action_name, piwik_idsite, piwik_url);
</script>
<noscript><p><img src="http://apps.sourceforge.net/piwik/openrocket/piwik.php?idsite=1" alt="" /></p></noscript>
<!-- End Piwik Tag -->
</body>
</html>

@ -1,134 +1,134 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>OpenRocket &mdash; Get involved!</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="keywords" content="OpenRocket, model rocket, simulator, simulation, rocketry" />
<link rel="stylesheet" type="text/css" href="layout.css" />
<meta name="Generator" content="htp 1.18" />
</head>
<body class="page_getinvolved">
<!--[if lte IE 6]>
<div id="iewarn">
You are using a browser that is <strong>8 years old!</strong>
&nbsp;&nbsp;&nbsp;
In Internet-years that is <em>prehistoric!</em><br/>
For the sanity of all webmasterkind,
<em>please <a href="http://www.mozilla.com/">upgrade</a></em>. It's easy!
</div>
<![endif]-->
<div class="menucontainer">
<div class="menu">
<div class="icon"><a href="index.html"></a></div>
<ul>
<li><a href="index.html">OpenRocket</a></li>
<li><a href="features.html">Features and screenshots</a></li>
<li><a href="download.html">Download</a></li>
<li><a href="documentation.html">Documentation</a></li>
<li><a href="http://wiki.openrocket.info/">Wiki pages</a></li>
<li><a href="http://openrocket.trans.free.fr/">Translations</a></li>
<li><a href="getinvolved.html">Get involved!</a></li>
<li><a href="contact.html">
Mailing lists<br/>
Support forums<br/>
Contact info</a></li>
<!--
<li><a href="report.html">
Report a bug<br/>
Request a feature</a></li>
-->
<li><a href="license.html">License</a></li>
</ul>
<div class="logo">
<a href="http://sourceforge.net/projects/openrocket"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=260357&amp;type=12" width="120" height="30" alt="Get OpenRocket at SourceForge.net. Fast, secure and Free Open Source software downloads" /></a>
</div>
</div>
</div>
<h1>Get involved in OpenRocket development</h1>
<div class="content">
<h2>How can I help OpenRocket?</h2>
<p>OpenRocket is an Open Source project, meaning that the source
code is freely available and anybody can help make the software
better. The program is mainly developed by Sampo Niskanen in
his free time. Help is very much appreciated. You don't even
need coding skills, as there are other things to do as well.</p>
<p>Below are a few suggestions of areas that would need help. If
you'd like to participate, please
<a href="https://lists.sourceforge.net/lists/listinfo/openrocket-devel">join
the development mailing list</a> and introduce your ideas there.</p>
<ul class="spacing">
<li><a href="#development">Java development</a></li>
<li><a href="#aerodynamics">Aerodynamic computation methods</a></li>
<li><a href="#documentation">Documentation</a></li>
<li><a href="#other">Other</a></li>
</ul>
<h3 id="development">Java development</h3>
<p>Below are a few ideas about what kind of input developers can
provide or features that could be implemented. For more
information see the feature roadmap in the distribution
<a href="http://openrocket.svn.sourceforge.net/viewvc/openrocket/trunk/TODO">TODO-file</a>.</p>
<ul>
<li>3D visualization of the rocket during design and flight
<span class="note"><em>(Help needed!)</em></span>
</li>
<li>Printing of designs, simulation results, fin planforms
etc</li>
<li>Memory profiling and leakage reduction</li>
<li>Writing RockSim design files</li>
<li>UI enhancements, for example zooming plots etc.</li>
</ul>
<h3 id="aerodynamics">Aerodynamic computation methods</h3>
<p>There is still work to be done in the aerodynamic computation
methods of OpenRocket. At least the following items need
help. I will gladly provide help in creating and even
implementing the computational methods.</p>
<ul>
<li>Simulating rockets at supersonic velocities (drag
coefficient and CG position).</li>
<li>Support for external pods and tube fins</li>
<li><acronym title="Computational Fluid Dynamics">CFD</acronym>
methods for simulation</li>
</ul>
<h3 id="documentation">Documentation tasks</h3>
<p>Contributions to the
<a href="http://wiki.openrocket.info/User%27s_Guide">OpenRocket
User's guide</a> are dearly needed. Below are examples of
topics.</p>
<ul>
<li>Getting started guide</li>
<li>How to make staged and clustered designs</li>
<li>Using mass/CG overrides for simulation accuracy</li>
<li>Using simulations</li>
<li>Effect of the simulation parameters</li>
<li>Simulation method limitations</li>
<li>Using simulation listeners (including examples)</li>
</ul>
<h3 id="other">Other</h3>
<ul>
<li><a href="http://openrocket.trans.free.fr/">Translating OpenRocket</a> to your language</li>
<li>Creating good and interesting example designs that
demonstrate some OpenRocket features.</li>
<li>Hosting a place to share rocket designs with other
enthusiasts.</li>
<li>Giving input and suggestions on how to make OpenRocket
better.</li>
</ul>
</div>
<div class="valid">
<p><a href="http://validator.w3.org/check/referer"><img src="valid-xhtml10.png" alt="Valid XHTML 1.0!" /></a>
</p>
</div>
<!-- Piwik -->
<script type="text/javascript">
var pkBaseURL = (("https:" == document.location.protocol) ? "https://apps.sourceforge.net/piwik/openrocket/" : "http://apps.sourceforge.net/piwik/openrocket/");
document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
piwik_action_name = '';
piwik_idsite = 1;
piwik_url = pkBaseURL + "piwik.php";
piwik_log(piwik_action_name, piwik_idsite, piwik_url);
</script>
<noscript><p><img src="http://apps.sourceforge.net/piwik/openrocket/piwik.php?idsite=1" alt="" /></p></noscript>
<!-- End Piwik Tag -->
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>OpenRocket &mdash; Get involved!</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="keywords" content="OpenRocket, model rocket, simulator, simulation, rocketry" />
<link rel="stylesheet" type="text/css" href="layout.css" />
<meta name="Generator" content="htp 1.18" />
</head>
<body class="page_getinvolved">
<!--[if lte IE 6]>
<div id="iewarn">
You are using a browser that is <strong>8 years old!</strong>
&nbsp;&nbsp;&nbsp;
In Internet-years that is <em>prehistoric!</em><br/>
For the sanity of all webmasterkind,
<em>please <a href="http://www.mozilla.com/">upgrade</a></em>. It's easy!
</div>
<![endif]-->
<div class="menucontainer">
<div class="menu">
<div class="icon"><a href="index.html"></a></div>
<ul>
<li><a href="index.html">OpenRocket</a></li>
<li><a href="features.html">Features and screenshots</a></li>
<li><a href="download.html">Download</a></li>
<li><a href="documentation.html">Documentation</a></li>
<li><a href="http://wiki.openrocket.info/">Wiki pages</a></li>
<li><a href="http://openrocket.trans.free.fr/">Translations</a></li>
<li><a href="getinvolved.html">Get involved!</a></li>
<li><a href="contact.html">
Mailing lists<br/>
Support forums<br/>
Contact info</a></li>
<!--
<li><a href="report.html">
Report a bug<br/>
Request a feature</a></li>
-->
<li><a href="license.html">License</a></li>
</ul>
<div class="logo">
<a href="http://sourceforge.net/projects/openrocket"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=260357&amp;type=12" width="120" height="30" alt="Get OpenRocket at SourceForge.net. Fast, secure and Free Open Source software downloads" /></a>
</div>
</div>
</div>
<h1>Get involved in OpenRocket development</h1>
<div class="content">
<h2>How can I help OpenRocket?</h2>
<p>OpenRocket is an Open Source project, meaning that the source
code is freely available and anybody can help make the software
better. The program is mainly developed by Sampo Niskanen in
his free time. Help is very much appreciated. You don't even
need coding skills, as there are other things to do as well.</p>
<p>Below are a few suggestions of areas that would need help. If
you'd like to participate, please
<a href="https://lists.sourceforge.net/lists/listinfo/openrocket-devel">join
the development mailing list</a> and introduce your ideas there.</p>
<ul class="spacing">
<li><a href="#development">Java development</a></li>
<li><a href="#aerodynamics">Aerodynamic computation methods</a></li>
<li><a href="#documentation">Documentation</a></li>
<li><a href="#other">Other</a></li>
</ul>
<h3 id="development">Java development</h3>
<p>Below are a few ideas about what kind of input developers can
provide or features that could be implemented. For more
information see the feature roadmap in the distribution
<a href="http://openrocket.svn.sourceforge.net/viewvc/openrocket/trunk/TODO">TODO-file</a>.</p>
<ul>
<li>3D visualization of the rocket during design and flight
<span class="note"><em>(Help needed!)</em></span>
</li>
<li>Printing of designs, simulation results, fin planforms
etc</li>
<li>Memory profiling and leakage reduction</li>
<li>Writing RockSim design files</li>
<li>UI enhancements, for example zooming plots etc.</li>
</ul>
<h3 id="aerodynamics">Aerodynamic computation methods</h3>
<p>There is still work to be done in the aerodynamic computation
methods of OpenRocket. At least the following items need
help. I will gladly provide help in creating and even
implementing the computational methods.</p>
<ul>
<li>Simulating rockets at supersonic velocities (drag
coefficient and CG position).</li>
<li>Support for external pods and tube fins</li>
<li><acronym title="Computational Fluid Dynamics">CFD</acronym>
methods for simulation</li>
</ul>
<h3 id="documentation">Documentation tasks</h3>
<p>Contributions to the
<a href="http://wiki.openrocket.info/User%27s_Guide">OpenRocket
User's guide</a> are dearly needed. Below are examples of
topics.</p>
<ul>
<li>Getting started guide</li>
<li>How to make staged and clustered designs</li>
<li>Using mass/CG overrides for simulation accuracy</li>
<li>Using simulations</li>
<li>Effect of the simulation parameters</li>
<li>Simulation method limitations</li>
<li>Using simulation listeners (including examples)</li>
</ul>
<h3 id="other">Other</h3>
<ul>
<li><a href="http://openrocket.trans.free.fr/">Translating OpenRocket</a> to your language</li>
<li>Creating good and interesting example designs that
demonstrate some OpenRocket features.</li>
<li>Hosting a place to share rocket designs with other
enthusiasts.</li>
<li>Giving input and suggestions on how to make OpenRocket
better.</li>
</ul>
</div>
<div class="valid">
<p><a href="http://validator.w3.org/check/referer"><img src="valid-xhtml10.png" alt="Valid XHTML 1.0!" /></a>
</p>
</div>
<!-- Piwik -->
<script type="text/javascript">
var pkBaseURL = (("https:" == document.location.protocol) ? "https://apps.sourceforge.net/piwik/openrocket/" : "http://apps.sourceforge.net/piwik/openrocket/");
document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
piwik_action_name = '';
piwik_idsite = 1;
piwik_url = pkBaseURL + "piwik.php";
piwik_log(piwik_action_name, piwik_idsite, piwik_url);
</script>
<noscript><p><img src="http://apps.sourceforge.net/piwik/openrocket/piwik.php?idsite=1" alt="" /></p></noscript>
<!-- End Piwik Tag -->
</body>
</html>

@ -1,342 +1,342 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>OpenRocket</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="keywords" content="OpenRocket, model rocket, simulator, simulation, rocketry" />
<link rel="stylesheet" type="text/css" href="layout.css" />
<meta name="Generator" content="htp 1.18" />
</head>
<body class="page_index">
<!--[if lte IE 6]>
<div id="iewarn">
You are using a browser that is <strong>8 years old!</strong>
&nbsp;&nbsp;&nbsp;
In Internet-years that is <em>prehistoric!</em><br/>
For the sanity of all webmasterkind,
<em>please <a href="http://www.mozilla.com/">upgrade</a></em>. It's easy!
</div>
<![endif]-->
<div class="menucontainer">
<div class="menu">
<div class="icon"><a href="index.html"></a></div>
<ul>
<li><a href="index.html">OpenRocket</a></li>
<li><a href="features.html">Features and screenshots</a></li>
<li><a href="download.html">Download</a></li>
<li><a href="documentation.html">Documentation</a></li>
<li><a href="http://wiki.openrocket.info/">Wiki pages</a></li>
<li><a href="http://openrocket.trans.free.fr/">Translations</a></li>
<li><a href="getinvolved.html">Get involved!</a></li>
<li><a href="contact.html">
Mailing lists<br/>
Support forums<br/>
Contact info</a></li>
<!--
<li><a href="report.html">
Report a bug<br/>
Request a feature</a></li>
-->
<li><a href="license.html">License</a></li>
</ul>
<div class="logo">
<a href="http://sourceforge.net/projects/openrocket"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=260357&amp;type=12" width="120" height="30" alt="Get OpenRocket at SourceForge.net. Fast, secure and Free Open Source software downloads" /></a>
</div>
</div>
</div>
<h1>OpenRocket &mdash; an Open Source model rocket simulator</h1>
<div class="content">
<h2>Introduction</h2>
<div class="rightpane">
<div class="downloadbox">
<a class="main" href="https://sourceforge.net/projects/openrocket/files/openrocket/15.03/OpenRocket-15.03.jar/download">
<strong>Download now!</strong>
<span>OpenRocket-15.03.jar</span>
</a>
<span class="alternative">
<a href="https://sourceforge.net/projects/openrocket/files/openrocket/15.03/ReleaseNotes/view">Release notes</a> |
<a href="download.html">Other versions</a>
</span>
</div>
<div class="screenshot">
<a href="shots/main.png"><img src="shots-small/main.jpg" alt="Main window" /></a>
<a href="features.html">
More screenshots...
</a>
</div>
<div class="support">
<a href="http://sourceforge.net/donate/index.php?group_id=260357"><img src="project-support.jpg" width="88" height="32" alt="Support This Project" /> </a>
</div>
<div class="support">
<a href="http://www.yourkit.com/java/profiler/index.jsp"><img src="yourkit.png" width="88" height="32" alt="YourKit Supports This Project" /> </a>
</div>
</div>
<p><strong>OpenRocket</strong> is a free, fully featured model
rocket simulator that allows you to design and simulate your
rockets before actually building and flying them.</p>
<p>The main features include:</p>
<ul>
<li>Six-degree-of-freedom flight simulation</li>
<li>Automatic design optimization</li>
<li>Realtime simulated altitude, velocity and acceleration display</li>
<li>Staging and clustering support</li>
<li>Cross-platform (Java-based)</li>
</ul>
<p>Read more about its <a
href="features.html">features and see screenshots</a>.
</p>
<p>OpenRocket is an Open Source project licensed under the
<a href="license.html">GNU GPL</a>. This means that the
software is free to use for whatever purposes, and the source
code is also available for studying and extending.
</p>
<p>OpenRocket needs help to become even better. Implementing
features, writing documentation and creating example designs are
just a few ways of helping. If you are interested in helping
make OpenRocket the best rocket simulator out there, please
<a href="getinvolved.html"><em>Get&nbsp;involved!</em></a>
</p>
<p>YourKit is supporting OpenRocket open source project with its
full-featured Java Profiler.
YourKit, LLC is the creator of innovative and intelligent tools for profiling
Java and .NET applications. Take a look at YourKit's leading software products:
<a href="http://www.yourkit.com/java/profiler/index.jsp">YourKit Java
Profiler</a> and
<a href="http://www.yourkit.com/.net/profiler/index.jsp">YourKit .NET
Profiler</a>.
</p>
<div class="clear"></div>
<div class="news">
<h2>News</h2>
<p><span class="date">28.03.2015:</span> Version 15.03 is
<a href="download.html">released</a>! This release contains scriptable simulation extensions and experimental support for tube fins along with many additional improvements.
</p>
<p><span class="date">02.11.2014:</span> Version 14.11 is
<a href="download.html">released</a>! This release contains very few changes. Thrustcurves have been updated and now include AeroTech DMS motors. A few bugs have been fixed.
</p>
<p><span class="date">25.06.2014:</span> Version 14.06 is
<a href="download.html">released</a>! This release contains very minimal changes. It fixes an annoying bug in tables that many people experience. A texture is added for Klima motors.
</p>
<p><span class="date">21.05.2014:</span> Version 14.05 is
<a href="download.html">released</a>! This release contains some minor features,
bug fixes and updated thrust curves. New motor vendors Klima and Southern
Cross Rocketry are included. The simulation will now compute optimum delay based
on actual coast time. Components with CG and mass overrides are decorated with
an icon in the component tree.
</p>
<p><span class="date">21.03.2014:</span> Version 14.03 is
<a href="download.html">released</a>! This release contains the
new photo realistic renderer (in the Tools menu) which allows one to visualize
the rocket in the air. There are various bug fixes in the configuration
and motor selection windows as well.
</p>
<p><span class="date">01.01.2014:</span> Version 13.11.2 is
<a href="download.html">released</a>! This release contains bug fixes,
usability improvements, and layout fixes.
</p>
<p><span class="date">15.11.2013:</span> Version 13.11.1 is
<a href="download.html">released</a>! This release contains bug fixes
including fixing Tube Coupler configuration, various exceptions in
the flight configuration tab, updated 3d libraris (which didn't really make
it into previous versions).</p>
<p><span class="date">8.11.2013:</span> Version 13.11 is
<a href="download.html">released</a>! This release simplifies
flight configurations by replacing the dialog with the configuration
tab. Motor filtering in the motor chooser dialog has been enhanced.
Chineese translations have been added and Russian translations updated.
Updated the 3D libraries, and squashed some bugs introduced by Java 1.7.0_45-b18.</p>
<p><span class="date">6.10.2013:</span> Version 13.09.1 is
<a href="download.html">released</a>! This is a bug-fix release,
and includes updated 3D libraries and new thrust curves for
Aerotech C3 and D2.</p>
<p><span class="date">8.9.2013:</span> Version 13.09 is
<a href="download.html">released</a>! This release contains
numerous bug fixes, updated 3D JOGL libraries, and separated
simulation edit and plot dialogs.</p>
<p><span class="date">4.5.2013:</span> Version 13.05 is
<a href="download.html">released</a>! This release contains a huge
number of improvements, the main ones including realistic 3D
rendering with decals, flight configurations, lower stage descent
simulation, boosted dart support and new translations for
Portuguese and Japanese. These are thanks to many
contributors.</p>
<p>Version 13.05 also changes the file format to be ZIP-based.
Versions earlier than 12.03 will not be able to read files saved
by this version.</p>
<p><span class="date">28.9.2012:</span> Version 12.09.1 is
<a href="download.html">released</a>! This is a bug-fix release,
fixing numerous bugs introduced in 12.09. The only new feature is
the option to automatically open the latest design file on startup
(in <em>Edit</em> &rarr; <em>Preferences</em> &rarr; <em>Options</em>).
<p><span class="date">23.9.2012:</span> Version 12.09 for Android is
<a href="download.html">released</a>! The major improvement is the
possibility to edit simulation parameters, thanks to work by Kevin
Ruland.</p>
<p><span class="date">16.9.2012:</span> Version 12.09 is
<a href="download.html">released</a>!</p>
<p>This version contains a huge number of new features by many contributors:</p>
<ul>
<li>3D rocket design view</li>
<li>Component Presets</li>
<li>Custom expressions in simulations</li>
<li>Printing for centering ring and clustered centering ring components</li>
<li>Support simple arthmatic in dimension entry</li>
<li>Support deploying recovery device at stage separation</li>
<li>Support for fractional inches (1/64) for unit length</li>
<li>Added preference for windspeed units separately</li>
<li>Added "most recently used files" in File Menu</li>
<li>Improved printed accurracy in fin marking guide</li>
<li>Calibration rulers added to printed templates</li>
<li>Translations in Czech and Polish, numerous updates</li>
</ul>
<p><span class="date">10.3.2012:</span> Version 12.03 for desktop
and Android is <a href="download.html">released</a>!</p>
<p>In this release the version numbering scheme has been changed.
From now on the version number is <em>YY.MM</em> indicating the
year and month of the release. Bug fix releases are indicated by
an added "<em>.1</em>".</p>
<p>This also marks the first release for Android devices. In this
first release you can open files and examine existing simulations,
stability data and motor files. The Android port is thanks to
work by Kevin Ruland.</p>
<p>Enhancements in the desktop version include saving designs in RKT
format thanks to Doug Pedrick, freeform fin set import form images
by Jason Blood, configurable stage separation
events, guided help tours and displaying the computed motor
designation class. The application has also been translated to
Italian by Mauro Biasutti and Russian by the Sky Dart Team.</p>
<p><span class="date">24.11.2011:</span> Version 1.1.9 is
<a href="download.html">released</a>!</p>
<p>For this version Richard Graham has implemented geodetic
computation methods, which take into account the curvature of the
Earth and the coriolis effect. The computation method is selected
by the <em>Geodetic calculations</em> option in the simulation
options. It's not <em>(yet)</em> a full spherical computation model, but
should be accurate enough for almost all sub-orbital needs.</p>
<p>Doug Pedrick has also enhanced the printing system with the
ability to print fin positioning guides, transition templates and
nose cone profiles. Other smaller enhancements and bug fixes are
also included.</p>
<p><span class="date">25.8.2011:</span> Version 1.1.8 is
<a href="download.html">released</a>!</p>
<p>This release contains bug fixes to the optimization methods.
It also contains a workaround to a JRE bug that prevents running
OpenRocket on some builds of Java 7.</p>
<p>The web pages have also been somewhat updated and Boris du Reau has
created <a href="http://openrocket.trans.free.fr/">a separate site</a>
for coordinating the localization efforts for OpenRocket.</p>
<p><span class="date">12.8.2011:</span> Version 1.1.7 is
<a href="download.html">released</a>!</p>
<p>This release includes automatic rocket design optimization
support (<em>Analyze</em> &rarr; <em>Rocket optimization</em>).
You can optimize any amount of rocket parameters for apogee
altitude, maximum velocity or a number of different values.</p>
<p>While the automatic optimization is a powerful tool, it is very
easy to optimize against particulars of the simulation methods,
instead of true physical phenomena. Always keep common sense at
hand and take the results with a grain of salt.</p>
<p><span class="date">22.7.2011:</span> Version 1.1.6 is
<a href="download.html">released</a>!</p>
<p>This release includes initial localization support and
translations to French, German and Spanish. This is thanks to the
great work of Boris du Reau, and the teams from Tripoli France,
Tripoli Spain and ERIG e.V. If you prefer to use some other
language than the system default, you can select the language on
the "Options" tab of the preferences dialog.</p>
<p>The release also includes design scaling support and numerous bug
fixes.</p>
<p><span class="date">10.6.2011:</span> Version 1.1.5 is
<a href="download.html">released</a>!</p>
<p>This release includes updates to the printing system which fixes
printing on Windows.</p>
<p><span class="date">5.3.2011:</span> Version 1.1.4 is
<a href="download.html">released</a>!</p>
<p>This release includes initial printing support, thanks to Doug
Pedrick. Printing still has a few issues on some platforms.
Various bugs have also been fixed.</p>
<p><span class="date">6.10.2010:</span> Version 1.1.3 is
<a href="download.html">released</a>!</p>
<p>This release includes support for moving and copying components
in the component tree using drag-and-drop. Use normal DnD for
moving, and control-drag for copy. This release also fixes a
severe bug in the undo system.</p>
<p><span class="date">7.9.2010:</span> A bug-fix version 1.1.2 is
<a href="download.html">released</a>!</p>
<p>This release fixes a severe bug in 1.1.1 that prevented adding stages
to rocket designs. Users are recommended to upgrade.</p>
<p><span class="date">3.9.2010:</span> Version 1.1.1 is
<a href="download.html">released</a>!</p>
<p>For this release a major part of the simulator code has been
rewritten for better flexibility in future development. It also
includes a vastly improved thrust curve selection dialog, the
possibility to loading user-defined thrust curves and better
startup times than previous releases.</p>
<p>Simulation listeners written for older versions of OpenRocket
are not compatible with this release.</p>
<p><span class="date">21.3.2010:</span> Version 1.1.0 is
<a href="download.html">released</a>!</p>
<p>This release includes the first support for loading RockSim
rocket design files (.RKT), thanks to contributions by Doug
Pedrick. It's also the kick-off of the 1.1 development branch of
OpenRocket.</p>
<p><span class="date">10.3.2010:</span> Version 1.0.0 is
<a href="download.html">released</a>!</p>
<p>This release includes several hundred new thrustcurves from
<a href="http://www.thrustcurve.org/">thrustcurve.org</a> and some
bug fixes. It is also a stable milestone, after which development
on larger features will be started in a 1.1 branch. Look out
for it! :-)</p>
<p><span class="date">17.2.2010:</span> Version 0.9.6 is
<a href="download.html">released</a>!</p>
<p>This release updates the aerodynamic calculation methods to be
more in line with the Barrowman method and enhances the simulation
time step selection, in addition to fixing numerous bugs.</p>
<p><span class="date">28.11.2009:</span> Version 0.9.5 is
<a href="download.html">released</a>!</p>
<p>This release <strong>fixes a serious bug in 0.9.4</strong> that
prevented adding a tube coupler and centering ring to the same
body tube, in addition to a few smaller additions. Users of
0.9.4 should upgrade immediately!</p>
<p><span class="date">24.11.2009:</span> Version 0.9.4 is
<a href="download.html">released</a>!</p>
<p>This version adds support for through-the-wall fin tabs,
attaching components to coupler tubes, material editing, automatic
update checking, in addition to fixing numerous bugs.</p>
<p><span class="date">1.9.2009:</span> Version 0.9.3 is
<a href="download.html">released</a>!</p>
<p>This version includes lots of bug fixes and new features including
data exporting, showing flight events in plots, example rocket designs,
splitting clustered inner tubes and automated bug reporting.</p>
<p><span class="date">13.7.2009:</span> Version 0.9.2 is
<a href="download.html">released</a>!</p>
<p>This version includes <strong>bug fixes for imperial unit
conversions</strong> and UI improvements for motor selection.
<em>All users of imperial units should upgrade!</em></p>
<p><span class="date">9.6.2009:</span> The
<a href="documentation.html">Master's thesis</a> for which OpenRocket
was written for is now available!</p>
<p>At the same time version 0.9.1 was
<a href="download.html">released</a>. This release fixes various
file handling bugs and adds small UI enhancements.</p>
<p><span class="date">24.5.2009:</span> First version 0.9.0
<a href="download.html">released</a>!</p>
</div>
</div>
<div class="valid">
<p><a href="http://validator.w3.org/check/referer"><img src="valid-xhtml10.png" alt="Valid XHTML 1.0!" /></a>
</p>
</div>
<!-- Piwik -->
<script type="text/javascript">
var pkBaseURL = (("https:" == document.location.protocol) ? "https://apps.sourceforge.net/piwik/openrocket/" : "http://apps.sourceforge.net/piwik/openrocket/");
document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
piwik_action_name = '';
piwik_idsite = 1;
piwik_url = pkBaseURL + "piwik.php";
piwik_log(piwik_action_name, piwik_idsite, piwik_url);
</script>
<noscript><p><img src="http://apps.sourceforge.net/piwik/openrocket/piwik.php?idsite=1" alt="" /></p></noscript>
<!-- End Piwik Tag -->
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>OpenRocket</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="keywords" content="OpenRocket, model rocket, simulator, simulation, rocketry" />
<link rel="stylesheet" type="text/css" href="layout.css" />
<meta name="Generator" content="htp 1.18" />
</head>
<body class="page_index">
<!--[if lte IE 6]>
<div id="iewarn">
You are using a browser that is <strong>8 years old!</strong>
&nbsp;&nbsp;&nbsp;
In Internet-years that is <em>prehistoric!</em><br/>
For the sanity of all webmasterkind,
<em>please <a href="http://www.mozilla.com/">upgrade</a></em>. It's easy!
</div>
<![endif]-->
<div class="menucontainer">
<div class="menu">
<div class="icon"><a href="index.html"></a></div>
<ul>
<li><a href="index.html">OpenRocket</a></li>
<li><a href="features.html">Features and screenshots</a></li>
<li><a href="download.html">Download</a></li>
<li><a href="documentation.html">Documentation</a></li>
<li><a href="http://wiki.openrocket.info/">Wiki pages</a></li>
<li><a href="http://openrocket.trans.free.fr/">Translations</a></li>
<li><a href="getinvolved.html">Get involved!</a></li>
<li><a href="contact.html">
Mailing lists<br/>
Support forums<br/>
Contact info</a></li>
<!--
<li><a href="report.html">
Report a bug<br/>
Request a feature</a></li>
-->
<li><a href="license.html">License</a></li>
</ul>
<div class="logo">
<a href="http://sourceforge.net/projects/openrocket"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=260357&amp;type=12" width="120" height="30" alt="Get OpenRocket at SourceForge.net. Fast, secure and Free Open Source software downloads" /></a>
</div>
</div>
</div>
<h1>OpenRocket &mdash; an Open Source model rocket simulator</h1>
<div class="content">
<h2>Introduction</h2>
<div class="rightpane">
<div class="downloadbox">
<a class="main" href="https://sourceforge.net/projects/openrocket/files/openrocket/15.03/OpenRocket-15.03.jar/download">
<strong>Download now!</strong>
<span>OpenRocket-15.03.jar</span>
</a>
<span class="alternative">
<a href="https://sourceforge.net/projects/openrocket/files/openrocket/15.03/ReleaseNotes/view">Release notes</a> |
<a href="download.html">Other versions</a>
</span>
</div>
<div class="screenshot">
<a href="shots/main.png"><img src="shots-small/main.jpg" alt="Main window" /></a>
<a href="features.html">
More screenshots...
</a>
</div>
<div class="support">
<a href="http://sourceforge.net/donate/index.php?group_id=260357"><img src="project-support.jpg" width="88" height="32" alt="Support This Project" /> </a>
</div>
<div class="support">
<a href="http://www.yourkit.com/java/profiler/index.jsp"><img src="yourkit.png" width="88" height="32" alt="YourKit Supports This Project" /> </a>
</div>
</div>
<p><strong>OpenRocket</strong> is a free, fully featured model
rocket simulator that allows you to design and simulate your
rockets before actually building and flying them.</p>
<p>The main features include:</p>
<ul>
<li>Six-degree-of-freedom flight simulation</li>
<li>Automatic design optimization</li>
<li>Realtime simulated altitude, velocity and acceleration display</li>
<li>Staging and clustering support</li>
<li>Cross-platform (Java-based)</li>
</ul>
<p>Read more about its <a
href="features.html">features and see screenshots</a>.
</p>
<p>OpenRocket is an Open Source project licensed under the
<a href="license.html">GNU GPL</a>. This means that the
software is free to use for whatever purposes, and the source
code is also available for studying and extending.
</p>
<p>OpenRocket needs help to become even better. Implementing
features, writing documentation and creating example designs are
just a few ways of helping. If you are interested in helping
make OpenRocket the best rocket simulator out there, please
<a href="getinvolved.html"><em>Get&nbsp;involved!</em></a>
</p>
<p>YourKit is supporting OpenRocket open source project with its
full-featured Java Profiler.
YourKit, LLC is the creator of innovative and intelligent tools for profiling
Java and .NET applications. Take a look at YourKit's leading software products:
<a href="http://www.yourkit.com/java/profiler/index.jsp">YourKit Java
Profiler</a> and
<a href="http://www.yourkit.com/.net/profiler/index.jsp">YourKit .NET
Profiler</a>.
</p>
<div class="clear"></div>
<div class="news">
<h2>News</h2>
<p><span class="date">28.03.2015:</span> Version 15.03 is
<a href="download.html">released</a>! This release contains scriptable simulation extensions and experimental support for tube fins along with many additional improvements.
</p>
<p><span class="date">02.11.2014:</span> Version 14.11 is
<a href="download.html">released</a>! This release contains very few changes. Thrustcurves have been updated and now include AeroTech DMS motors. A few bugs have been fixed.
</p>
<p><span class="date">25.06.2014:</span> Version 14.06 is
<a href="download.html">released</a>! This release contains very minimal changes. It fixes an annoying bug in tables that many people experience. A texture is added for Klima motors.
</p>
<p><span class="date">21.05.2014:</span> Version 14.05 is
<a href="download.html">released</a>! This release contains some minor features,
bug fixes and updated thrust curves. New motor vendors Klima and Southern
Cross Rocketry are included. The simulation will now compute optimum delay based
on actual coast time. Components with CG and mass overrides are decorated with
an icon in the component tree.
</p>
<p><span class="date">21.03.2014:</span> Version 14.03 is
<a href="download.html">released</a>! This release contains the
new photo realistic renderer (in the Tools menu) which allows one to visualize
the rocket in the air. There are various bug fixes in the configuration
and motor selection windows as well.
</p>
<p><span class="date">01.01.2014:</span> Version 13.11.2 is
<a href="download.html">released</a>! This release contains bug fixes,
usability improvements, and layout fixes.
</p>
<p><span class="date">15.11.2013:</span> Version 13.11.1 is
<a href="download.html">released</a>! This release contains bug fixes
including fixing Tube Coupler configuration, various exceptions in
the flight configuration tab, updated 3d libraris (which didn't really make
it into previous versions).</p>
<p><span class="date">8.11.2013:</span> Version 13.11 is
<a href="download.html">released</a>! This release simplifies
flight configurations by replacing the dialog with the configuration
tab. Motor filtering in the motor chooser dialog has been enhanced.
Chineese translations have been added and Russian translations updated.
Updated the 3D libraries, and squashed some bugs introduced by Java 1.7.0_45-b18.</p>
<p><span class="date">6.10.2013:</span> Version 13.09.1 is
<a href="download.html">released</a>! This is a bug-fix release,
and includes updated 3D libraries and new thrust curves for
Aerotech C3 and D2.</p>
<p><span class="date">8.9.2013:</span> Version 13.09 is
<a href="download.html">released</a>! This release contains
numerous bug fixes, updated 3D JOGL libraries, and separated
simulation edit and plot dialogs.</p>
<p><span class="date">4.5.2013:</span> Version 13.05 is
<a href="download.html">released</a>! This release contains a huge
number of improvements, the main ones including realistic 3D
rendering with decals, flight configurations, lower stage descent
simulation, boosted dart support and new translations for
Portuguese and Japanese. These are thanks to many
contributors.</p>
<p>Version 13.05 also changes the file format to be ZIP-based.
Versions earlier than 12.03 will not be able to read files saved
by this version.</p>
<p><span class="date">28.9.2012:</span> Version 12.09.1 is
<a href="download.html">released</a>! This is a bug-fix release,
fixing numerous bugs introduced in 12.09. The only new feature is
the option to automatically open the latest design file on startup
(in <em>Edit</em> &rarr; <em>Preferences</em> &rarr; <em>Options</em>).
<p><span class="date">23.9.2012:</span> Version 12.09 for Android is
<a href="download.html">released</a>! The major improvement is the
possibility to edit simulation parameters, thanks to work by Kevin
Ruland.</p>
<p><span class="date">16.9.2012:</span> Version 12.09 is
<a href="download.html">released</a>!</p>
<p>This version contains a huge number of new features by many contributors:</p>
<ul>
<li>3D rocket design view</li>
<li>Component Presets</li>
<li>Custom expressions in simulations</li>
<li>Printing for centering ring and clustered centering ring components</li>
<li>Support simple arthmatic in dimension entry</li>
<li>Support deploying recovery device at stage separation</li>
<li>Support for fractional inches (1/64) for unit length</li>
<li>Added preference for windspeed units separately</li>
<li>Added "most recently used files" in File Menu</li>
<li>Improved printed accurracy in fin marking guide</li>
<li>Calibration rulers added to printed templates</li>
<li>Translations in Czech and Polish, numerous updates</li>
</ul>
<p><span class="date">10.3.2012:</span> Version 12.03 for desktop
and Android is <a href="download.html">released</a>!</p>
<p>In this release the version numbering scheme has been changed.
From now on the version number is <em>YY.MM</em> indicating the
year and month of the release. Bug fix releases are indicated by
an added "<em>.1</em>".</p>
<p>This also marks the first release for Android devices. In this
first release you can open files and examine existing simulations,
stability data and motor files. The Android port is thanks to
work by Kevin Ruland.</p>
<p>Enhancements in the desktop version include saving designs in RKT
format thanks to Doug Pedrick, freeform fin set import form images
by Jason Blood, configurable stage separation
events, guided help tours and displaying the computed motor
designation class. The application has also been translated to
Italian by Mauro Biasutti and Russian by the Sky Dart Team.</p>
<p><span class="date">24.11.2011:</span> Version 1.1.9 is
<a href="download.html">released</a>!</p>
<p>For this version Richard Graham has implemented geodetic
computation methods, which take into account the curvature of the
Earth and the coriolis effect. The computation method is selected
by the <em>Geodetic calculations</em> option in the simulation
options. It's not <em>(yet)</em> a full spherical computation model, but
should be accurate enough for almost all sub-orbital needs.</p>
<p>Doug Pedrick has also enhanced the printing system with the
ability to print fin positioning guides, transition templates and
nose cone profiles. Other smaller enhancements and bug fixes are
also included.</p>
<p><span class="date">25.8.2011:</span> Version 1.1.8 is
<a href="download.html">released</a>!</p>
<p>This release contains bug fixes to the optimization methods.
It also contains a workaround to a JRE bug that prevents running
OpenRocket on some builds of Java 7.</p>
<p>The web pages have also been somewhat updated and Boris du Reau has
created <a href="http://openrocket.trans.free.fr/">a separate site</a>
for coordinating the localization efforts for OpenRocket.</p>
<p><span class="date">12.8.2011:</span> Version 1.1.7 is
<a href="download.html">released</a>!</p>
<p>This release includes automatic rocket design optimization
support (<em>Analyze</em> &rarr; <em>Rocket optimization</em>).
You can optimize any amount of rocket parameters for apogee
altitude, maximum velocity or a number of different values.</p>
<p>While the automatic optimization is a powerful tool, it is very
easy to optimize against particulars of the simulation methods,
instead of true physical phenomena. Always keep common sense at
hand and take the results with a grain of salt.</p>
<p><span class="date">22.7.2011:</span> Version 1.1.6 is
<a href="download.html">released</a>!</p>
<p>This release includes initial localization support and
translations to French, German and Spanish. This is thanks to the
great work of Boris du Reau, and the teams from Tripoli France,
Tripoli Spain and ERIG e.V. If you prefer to use some other
language than the system default, you can select the language on
the "Options" tab of the preferences dialog.</p>
<p>The release also includes design scaling support and numerous bug
fixes.</p>
<p><span class="date">10.6.2011:</span> Version 1.1.5 is
<a href="download.html">released</a>!</p>
<p>This release includes updates to the printing system which fixes
printing on Windows.</p>
<p><span class="date">5.3.2011:</span> Version 1.1.4 is
<a href="download.html">released</a>!</p>
<p>This release includes initial printing support, thanks to Doug
Pedrick. Printing still has a few issues on some platforms.
Various bugs have also been fixed.</p>
<p><span class="date">6.10.2010:</span> Version 1.1.3 is
<a href="download.html">released</a>!</p>
<p>This release includes support for moving and copying components
in the component tree using drag-and-drop. Use normal DnD for
moving, and control-drag for copy. This release also fixes a
severe bug in the undo system.</p>
<p><span class="date">7.9.2010:</span> A bug-fix version 1.1.2 is
<a href="download.html">released</a>!</p>
<p>This release fixes a severe bug in 1.1.1 that prevented adding stages
to rocket designs. Users are recommended to upgrade.</p>
<p><span class="date">3.9.2010:</span> Version 1.1.1 is
<a href="download.html">released</a>!</p>
<p>For this release a major part of the simulator code has been
rewritten for better flexibility in future development. It also
includes a vastly improved thrust curve selection dialog, the
possibility to loading user-defined thrust curves and better
startup times than previous releases.</p>
<p>Simulation listeners written for older versions of OpenRocket
are not compatible with this release.</p>
<p><span class="date">21.3.2010:</span> Version 1.1.0 is
<a href="download.html">released</a>!</p>
<p>This release includes the first support for loading RockSim
rocket design files (.RKT), thanks to contributions by Doug
Pedrick. It's also the kick-off of the 1.1 development branch of
OpenRocket.</p>
<p><span class="date">10.3.2010:</span> Version 1.0.0 is
<a href="download.html">released</a>!</p>
<p>This release includes several hundred new thrustcurves from
<a href="http://www.thrustcurve.org/">thrustcurve.org</a> and some
bug fixes. It is also a stable milestone, after which development
on larger features will be started in a 1.1 branch. Look out
for it! :-)</p>
<p><span class="date">17.2.2010:</span> Version 0.9.6 is
<a href="download.html">released</a>!</p>
<p>This release updates the aerodynamic calculation methods to be
more in line with the Barrowman method and enhances the simulation
time step selection, in addition to fixing numerous bugs.</p>
<p><span class="date">28.11.2009:</span> Version 0.9.5 is
<a href="download.html">released</a>!</p>
<p>This release <strong>fixes a serious bug in 0.9.4</strong> that
prevented adding a tube coupler and centering ring to the same
body tube, in addition to a few smaller additions. Users of
0.9.4 should upgrade immediately!</p>
<p><span class="date">24.11.2009:</span> Version 0.9.4 is
<a href="download.html">released</a>!</p>
<p>This version adds support for through-the-wall fin tabs,
attaching components to coupler tubes, material editing, automatic
update checking, in addition to fixing numerous bugs.</p>
<p><span class="date">1.9.2009:</span> Version 0.9.3 is
<a href="download.html">released</a>!</p>
<p>This version includes lots of bug fixes and new features including
data exporting, showing flight events in plots, example rocket designs,
splitting clustered inner tubes and automated bug reporting.</p>
<p><span class="date">13.7.2009:</span> Version 0.9.2 is
<a href="download.html">released</a>!</p>
<p>This version includes <strong>bug fixes for imperial unit
conversions</strong> and UI improvements for motor selection.
<em>All users of imperial units should upgrade!</em></p>
<p><span class="date">9.6.2009:</span> The
<a href="documentation.html">Master's thesis</a> for which OpenRocket
was written for is now available!</p>
<p>At the same time version 0.9.1 was
<a href="download.html">released</a>. This release fixes various
file handling bugs and adds small UI enhancements.</p>
<p><span class="date">24.5.2009:</span> First version 0.9.0
<a href="download.html">released</a>!</p>
</div>
</div>
<div class="valid">
<p><a href="http://validator.w3.org/check/referer"><img src="valid-xhtml10.png" alt="Valid XHTML 1.0!" /></a>
</p>
</div>
<!-- Piwik -->
<script type="text/javascript">
var pkBaseURL = (("https:" == document.location.protocol) ? "https://apps.sourceforge.net/piwik/openrocket/" : "http://apps.sourceforge.net/piwik/openrocket/");
document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
piwik_action_name = '';
piwik_idsite = 1;
piwik_url = pkBaseURL + "piwik.php";
piwik_log(piwik_action_name, piwik_idsite, piwik_url);
</script>
<noscript><p><img src="http://apps.sourceforge.net/piwik/openrocket/piwik.php?idsite=1" alt="" /></p></noscript>
<!-- End Piwik Tag -->
</body>
</html>

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Before

Width:  |  Height:  |  Size: 129 KiB

After

Width:  |  Height:  |  Size: 129 KiB

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

@ -0,0 +1,485 @@
<?xml version="1.0" encoding="UTF-8"?>
<install4j version="8.0.4" transformSequenceNumber="8">
<directoryPresets config="/Users/jhanney/Code/openrocket-installer-files/20.x" />
<application name="OpenRocket 20.x" applicationId="8434-9327-1469-6373" mediaDir="media" shortName="OpenRocket" publisher="OpenRocket" publisherWeb="http://openrocket.info" version="20.x" macVolumeId="5f58a2be20d8e22f" javaMinVersion="11.0" javaMaxVersion="11.0" jdkMode="jdk" jdkName="JDK 11.0">
<jreBundles jdkProviderId="AdoptOpenJDK" release="openjdk11/jdk-11.0.6+10">
<modules>
<defaultModules set="jre" />
<module name="java.scripting" />
</modules>
</jreBundles>
</application>
<files>
<mountPoints>
<mountPoint id="58" />
</mountPoints>
<entries>
<fileEntry mountPoint="58" file="/Users/jhanney/Code/openrocket/swing/build/jar/OpenRocket.jar" />
</entries>
</files>
<launchers>
<launcher name="OpenRocket 20.x" id="59" icnsFile="/Users/jhanney/Code/openrocket-installer-files/20.x/OpenRocket.icns">
<executable name="OpenRocket" iconSet="true" executableDir="." executableMode="gui" />
<java mainClass="net.sf.openrocket.startup.OpenRocket">
<classPath>
<archive location="OpenRocket.jar" failOnError="false" />
</classPath>
</java>
<iconImageFiles>
<file path="/Users/jhanney/Code/openrocket/core/resources-src/pix/icon/icon-048.png" />
</iconImageFiles>
</launcher>
</launchers>
<installerGui>
<applications>
<application id="installer" beanClass="com.install4j.runtime.beans.applications.InstallerApplication">
<startup>
<screen id="1" beanClass="com.install4j.runtime.beans.screens.StartupScreen" rollbackBarrierExitCode="0">
<actions>
<action id="22" beanClass="com.install4j.runtime.beans.actions.misc.RequestPrivilegesAction" actionElevationType="none" rollbackBarrierExitCode="0" />
</actions>
</screen>
</startup>
<screens>
<screen id="2" beanClass="com.install4j.runtime.beans.screens.WelcomeScreen" styleId="41" rollbackBarrierExitCode="0">
<actions>
<action id="7" beanClass="com.install4j.runtime.beans.actions.misc.LoadResponseFileAction" rollbackBarrierExitCode="0" multiExec="true">
<serializedBean>
<property name="excludedVariables" type="array" elementType="string" length="1">
<element index="0">sys.installationDir</element>
</property>
</serializedBean>
<condition>context.getBooleanVariable("sys.confirmedUpdateInstallation")</condition>
</action>
</actions>
<formComponents>
<formComponent id="3" beanClass="com.install4j.runtime.beans.formcomponents.MultilineLabelComponent">
<serializedBean>
<property name="labelText" type="string">${form:welcomeMessage}</property>
</serializedBean>
<visibilityScript>!context.isConsole()</visibilityScript>
</formComponent>
<formComponent id="4" beanClass="com.install4j.runtime.beans.formcomponents.ConsoleHandlerFormComponent">
<serializedBean>
<property name="consoleScript">
<object class="com.install4j.api.beans.ScriptProperty">
<property name="value" type="string">String message = context.getMessage("ConsoleWelcomeLabel", context.getApplicationName());
return console.askOkCancel(message, true);
</property>
</object>
</property>
</serializedBean>
</formComponent>
<formComponent id="5" beanClass="com.install4j.runtime.beans.formcomponents.UpdateAlertComponent" useExternalParametrization="true" externalParametrizationName="Update Alert" externalParametrizationMode="include">
<externalParametrizationPropertyNames>
<propertyName>updateCheck</propertyName>
</externalParametrizationPropertyNames>
</formComponent>
<formComponent id="6" beanClass="com.install4j.runtime.beans.formcomponents.MultilineLabelComponent" insetTop="20">
<serializedBean>
<property name="labelText" type="string">${i18n:ClickNext}</property>
</serializedBean>
</formComponent>
</formComponents>
</screen>
<screen id="8" beanClass="com.install4j.runtime.beans.screens.InstallationDirectoryScreen" rollbackBarrierExitCode="0">
<condition>!context.getBooleanVariable("sys.confirmedUpdateInstallation")</condition>
<actions>
<action id="11" beanClass="com.install4j.runtime.beans.actions.misc.LoadResponseFileAction" rollbackBarrierExitCode="0" multiExec="true">
<serializedBean>
<property name="excludedVariables" type="array" elementType="string" length="1">
<element index="0">sys.installationDir</element>
</property>
</serializedBean>
<condition>context.getVariable("sys.responseFile") == null</condition>
</action>
</actions>
<formComponents>
<formComponent id="9" beanClass="com.install4j.runtime.beans.formcomponents.MultilineLabelComponent" insetBottom="25">
<serializedBean>
<property name="labelText" type="string">${i18n:SelectDirLabel(${compiler:sys.fullName})}</property>
</serializedBean>
</formComponent>
<formComponent id="10" beanClass="com.install4j.runtime.beans.formcomponents.InstallationDirectoryChooserComponent" useExternalParametrization="true" externalParametrizationName="Installation Directory Chooser" externalParametrizationMode="include">
<serializedBean>
<property name="requestFocus" type="boolean" value="true" />
</serializedBean>
<externalParametrizationPropertyNames>
<propertyName>suggestAppDir</propertyName>
<propertyName>validateApplicationId</propertyName>
<propertyName>existingDirWarning</propertyName>
<propertyName>checkWritable</propertyName>
<propertyName>manualEntryAllowed</propertyName>
<propertyName>checkFreeSpace</propertyName>
<propertyName>showRequiredDiskSpace</propertyName>
<propertyName>showFreeDiskSpace</propertyName>
<propertyName>allowSpacesOnUnix</propertyName>
<propertyName>validationScript</propertyName>
<propertyName>standardValidation</propertyName>
</externalParametrizationPropertyNames>
</formComponent>
</formComponents>
</screen>
<screen id="12" beanClass="com.install4j.runtime.beans.screens.ComponentsScreen" rollbackBarrierExitCode="0">
<formComponents>
<formComponent id="13" beanClass="com.install4j.runtime.beans.formcomponents.MultilineLabelComponent">
<serializedBean>
<property name="labelText" type="string">${i18n:SelectComponentsLabel2}</property>
</serializedBean>
<visibilityScript>!context.isConsole()</visibilityScript>
</formComponent>
<formComponent id="14" beanClass="com.install4j.runtime.beans.formcomponents.ComponentSelectorComponent" useExternalParametrization="true" externalParametrizationName="Installation Components" externalParametrizationMode="include">
<serializedBean>
<property name="fillVertical" type="boolean" value="true" />
</serializedBean>
<externalParametrizationPropertyNames>
<propertyName>selectionChangedScript</propertyName>
</externalParametrizationPropertyNames>
</formComponent>
</formComponents>
</screen>
<screen id="164" beanClass="com.install4j.runtime.beans.screens.FileAssociationsScreen" rollbackBarrierExitCode="0">
<actions>
<action id="167" beanClass="com.install4j.runtime.beans.actions.desktop.CreateFileAssociationAction" actionElevationType="elevated" rollbackBarrierExitCode="0">
<serializedBean>
<property name="description" type="string">OpenRocket Rocket Files</property>
<property name="extension" type="string">ork</property>
<property name="launcherId" type="string">59</property>
</serializedBean>
</action>
</actions>
<formComponents>
<formComponent id="165" beanClass="com.install4j.runtime.beans.formcomponents.MultilineLabelComponent">
<serializedBean>
<property name="labelText" type="string">${i18n:SelectAssociationsLabel}</property>
</serializedBean>
</formComponent>
<formComponent id="166" beanClass="com.install4j.runtime.beans.formcomponents.FileAssociationsComponent" useExternalParametrization="true" externalParametrizationName="File Associations" externalParametrizationMode="include">
<serializedBean>
<property name="fillVertical" type="boolean" value="true" />
</serializedBean>
<externalParametrizationPropertyNames>
<propertyName>showSelectionButtons</propertyName>
<propertyName>selectionButtonPosition</propertyName>
</externalParametrizationPropertyNames>
</formComponent>
</formComponents>
</screen>
<screen id="15" beanClass="com.install4j.runtime.beans.screens.InstallationScreen" rollbackBarrier="true" rollbackBarrierExitCode="0">
<actions>
<action id="17" beanClass="com.install4j.runtime.beans.actions.InstallFilesAction" actionElevationType="elevated" rollbackBarrierExitCode="0" failureStrategy="quit" errorMessage="${i18n:FileCorrupted}" />
<action id="18" beanClass="com.install4j.runtime.beans.actions.desktop.CreateProgramGroupAction" actionElevationType="elevated" rollbackBarrierExitCode="0">
<serializedBean>
<property name="uninstallerMenuName" type="string">${i18n:UninstallerMenuEntry(${compiler:sys.fullName})}</property>
</serializedBean>
<condition>!context.getBooleanVariable("sys.programGroupDisabled")</condition>
</action>
<action id="19" beanClass="com.install4j.runtime.beans.actions.desktop.RegisterAddRemoveAction" actionElevationType="elevated" rollbackBarrierExitCode="0">
<serializedBean>
<property name="itemName" type="string">${compiler:sys.fullName} ${compiler:sys.version}</property>
</serializedBean>
</action>
</actions>
<formComponents>
<formComponent id="16" beanClass="com.install4j.runtime.beans.formcomponents.ProgressComponent">
<serializedBean>
<property name="initialStatusMessage" type="string">${i18n:WizardPreparing}</property>
</serializedBean>
</formComponent>
</formComponents>
</screen>
<screen id="20" beanClass="com.install4j.runtime.beans.screens.FinishedScreen" styleId="41" rollbackBarrierExitCode="0" finishScreen="true">
<formComponents>
<formComponent id="21" beanClass="com.install4j.runtime.beans.formcomponents.MultilineLabelComponent" insetBottom="10">
<serializedBean>
<property name="labelText" type="string">${form:finishedMessage}</property>
</serializedBean>
</formComponent>
</formComponents>
</screen>
</screens>
</application>
<application id="uninstaller" beanClass="com.install4j.runtime.beans.applications.UninstallerApplication">
<serializedBean>
<property name="customMacosExecutableName" type="string">${i18n:UninstallerMenuEntry(${compiler:sys.fullName})}</property>
<property name="useCustomMacosExecutableName" type="boolean" value="true" />
</serializedBean>
<startup>
<screen id="23" beanClass="com.install4j.runtime.beans.screens.StartupScreen" rollbackBarrierExitCode="0">
<actions>
<action id="33" beanClass="com.install4j.runtime.beans.actions.misc.LoadResponseFileAction" rollbackBarrierExitCode="0" />
<action id="34" beanClass="com.install4j.runtime.beans.actions.misc.RequireInstallerPrivilegesAction" actionElevationType="none" rollbackBarrierExitCode="0" />
</actions>
</screen>
</startup>
<screens>
<screen id="24" beanClass="com.install4j.runtime.beans.screens.UninstallWelcomeScreen" styleId="41" rollbackBarrierExitCode="0">
<formComponents>
<formComponent id="25" beanClass="com.install4j.runtime.beans.formcomponents.MultilineLabelComponent" insetBottom="10">
<serializedBean>
<property name="labelText" type="string">${form:welcomeMessage}</property>
</serializedBean>
<visibilityScript>!context.isConsole()</visibilityScript>
</formComponent>
<formComponent id="26" beanClass="com.install4j.runtime.beans.formcomponents.ConsoleHandlerFormComponent">
<serializedBean>
<property name="consoleScript">
<object class="com.install4j.api.beans.ScriptProperty">
<property name="value" type="string">String message = context.getMessage("ConfirmUninstall", context.getApplicationName());
return console.askYesNo(message, true);
</property>
</object>
</property>
</serializedBean>
</formComponent>
</formComponents>
</screen>
<screen id="27" beanClass="com.install4j.runtime.beans.screens.UninstallationScreen" rollbackBarrierExitCode="0">
<actions>
<action id="29" beanClass="com.install4j.runtime.beans.actions.UninstallFilesAction" actionElevationType="elevated" rollbackBarrierExitCode="0" />
</actions>
<formComponents>
<formComponent id="28" beanClass="com.install4j.runtime.beans.formcomponents.ProgressComponent">
<serializedBean>
<property name="initialStatusMessage" type="string">${i18n:UninstallerPreparing}</property>
</serializedBean>
</formComponent>
</formComponents>
</screen>
<screen id="32" beanClass="com.install4j.runtime.beans.screens.UninstallFailureScreen" rollbackBarrierExitCode="0" finishScreen="true" />
<screen id="30" beanClass="com.install4j.runtime.beans.screens.UninstallSuccessScreen" styleId="41" rollbackBarrierExitCode="0" finishScreen="true">
<formComponents>
<formComponent id="31" beanClass="com.install4j.runtime.beans.formcomponents.MultilineLabelComponent" insetBottom="10">
<serializedBean>
<property name="labelText" type="string">${form:successMessage}</property>
</serializedBean>
</formComponent>
</formComponents>
</screen>
</screens>
</application>
</applications>
<styles defaultStyleId="35">
<style name="Standard" id="35" beanClass="com.install4j.runtime.beans.styles.FormStyle">
<formComponents>
<formComponent name="Header" id="36" beanClass="com.install4j.runtime.beans.styles.NestedStyleComponent" insetTop="0" insetBottom="0">
<serializedBean>
<property name="styleId" type="string">48</property>
</serializedBean>
</formComponent>
<group name="Main" id="37" beanClass="com.install4j.runtime.beans.groups.VerticalFormComponentGroup">
<beans>
<formComponent id="38" beanClass="com.install4j.runtime.beans.styles.ContentComponent" insetTop="10" insetLeft="20" insetBottom="10" insetRight="20" />
<formComponent name="Watermark" id="39" beanClass="com.install4j.runtime.beans.formcomponents.SeparatorComponent" insetTop="0" insetLeft="5" insetBottom="0" useExternalParametrization="true" externalParametrizationName="Custom watermark" externalParametrizationMode="include">
<serializedBean>
<property name="enabledTitleText" type="boolean" value="false" />
<property name="labelText" type="string">install4j</property>
</serializedBean>
<externalParametrizationPropertyNames>
<propertyName>labelText</propertyName>
</externalParametrizationPropertyNames>
</formComponent>
<formComponent name="Footer" id="40" beanClass="com.install4j.runtime.beans.styles.NestedStyleComponent" insetTop="0" insetBottom="0">
<serializedBean>
<property name="styleId" type="string">52</property>
</serializedBean>
</formComponent>
</beans>
</group>
</formComponents>
</style>
<style name="Banner" id="41" beanClass="com.install4j.runtime.beans.styles.FormStyle">
<formComponents>
<group id="42" beanClass="com.install4j.runtime.beans.groups.VerticalFormComponentGroup" useExternalParametrization="true" externalParametrizationName="Customize banner image" externalParametrizationMode="include">
<serializedBean>
<property name="backgroundColor">
<object class="java.awt.Color">
<int>255</int>
<int>255</int>
<int>255</int>
<int>255</int>
</object>
</property>
<property name="borderSides">
<object class="com.install4j.runtime.beans.formcomponents.BorderSides">
<property name="bottom" type="boolean" value="true" />
</object>
</property>
<property name="imageEdgeBackgroundColor">
<object class="java.awt.Color">
<int>25</int>
<int>143</int>
<int>220</int>
<int>255</int>
</object>
</property>
<property name="imageEdgeBorder" type="boolean" value="true" />
<property name="imageFile">
<object class="com.install4j.api.beans.ExternalFile">
<string>${compiler:sys.install4jHome}/resource/styles/wizard.png</string>
</object>
</property>
<property name="insets">
<object class="java.awt.Insets">
<int>5</int>
<int>10</int>
<int>10</int>
<int>10</int>
</object>
</property>
</serializedBean>
<beans>
<formComponent id="43" beanClass="com.install4j.runtime.beans.styles.ScreenTitleComponent" insetTop="0">
<serializedBean>
<property name="labelFontSizePercent" type="int" value="130" />
<property name="labelFontStyle" type="enum" class="com.install4j.runtime.beans.formcomponents.FontStyle" value="BOLD" />
<property name="labelFontType" type="enum" class="com.install4j.runtime.beans.formcomponents.FontType" value="DERIVED" />
</serializedBean>
</formComponent>
<formComponent id="44" beanClass="com.install4j.runtime.beans.formcomponents.SeparatorComponent" />
<formComponent id="45" beanClass="com.install4j.runtime.beans.styles.ContentComponent" insetTop="10" insetBottom="0" />
</beans>
<externalParametrizationPropertyNames>
<propertyName>imageAnchor</propertyName>
<propertyName>imageEdgeBackgroundColor</propertyName>
<propertyName>imageFile</propertyName>
</externalParametrizationPropertyNames>
</group>
<formComponent id="46" beanClass="com.install4j.runtime.beans.styles.NestedStyleComponent" insetBottom="0">
<serializedBean>
<property name="styleId" type="string">52</property>
</serializedBean>
</formComponent>
</formComponents>
</style>
<group name="Style components" id="47" beanClass="com.install4j.runtime.beans.groups.StyleGroup">
<beans>
<style name="Standard header" id="48" beanClass="com.install4j.runtime.beans.styles.FormStyle">
<serializedBean>
<property name="fillVertical" type="boolean" value="false" />
<property name="standalone" type="boolean" value="false" />
<property name="verticalAnchor" type="enum" class="com.install4j.api.beans.Anchor" value="NORTH" />
</serializedBean>
<formComponents>
<group id="49" beanClass="com.install4j.runtime.beans.groups.VerticalFormComponentGroup" useExternalParametrization="true" externalParametrizationName="Customize title bar" externalParametrizationMode="include">
<serializedBean>
<property name="backgroundColor">
<object class="java.awt.Color">
<int>255</int>
<int>255</int>
<int>255</int>
<int>255</int>
</object>
</property>
<property name="borderSides">
<object class="com.install4j.runtime.beans.formcomponents.BorderSides">
<property name="bottom" type="boolean" value="true" />
</object>
</property>
<property name="imageAnchor" type="enum" class="com.install4j.api.beans.Anchor" value="NORTHEAST" />
<property name="imageEdgeBorderWidth" type="int" value="2" />
<property name="imageFile">
<object class="com.install4j.api.beans.ExternalFile">
<string>icon:${installer:sys.installerApplicationMode}_header.png</string>
</object>
</property>
<property name="imageInsets">
<object class="java.awt.Insets">
<int>0</int>
<int>5</int>
<int>1</int>
<int>1</int>
</object>
</property>
<property name="insets">
<object class="java.awt.Insets">
<int>0</int>
<int>20</int>
<int>0</int>
<int>10</int>
</object>
</property>
</serializedBean>
<beans>
<formComponent name="Title" id="50" beanClass="com.install4j.runtime.beans.styles.ScreenTitleComponent">
<serializedBean>
<property name="labelFontStyle" type="enum" class="com.install4j.runtime.beans.formcomponents.FontStyle" value="BOLD" />
<property name="labelFontType" type="enum" class="com.install4j.runtime.beans.formcomponents.FontType" value="DERIVED" />
</serializedBean>
</formComponent>
<formComponent name="Subtitle" id="51" beanClass="com.install4j.runtime.beans.styles.ScreenTitleComponent" insetLeft="8">
<serializedBean>
<property name="titleType" type="enum" class="com.install4j.runtime.beans.styles.TitleType" value="SUB_TITLE" />
</serializedBean>
</formComponent>
</beans>
<externalParametrizationPropertyNames>
<propertyName>backgroundColor</propertyName>
<propertyName>foregroundColor</propertyName>
<propertyName>imageAnchor</propertyName>
<propertyName>imageFile</propertyName>
<propertyName>imageOverlap</propertyName>
</externalParametrizationPropertyNames>
</group>
</formComponents>
</style>
<style name="Standard footer" id="52" beanClass="com.install4j.runtime.beans.styles.FormStyle">
<serializedBean>
<property name="fillVertical" type="boolean" value="false" />
<property name="standalone" type="boolean" value="false" />
<property name="verticalAnchor" type="enum" class="com.install4j.api.beans.Anchor" value="SOUTH" />
</serializedBean>
<formComponents>
<group id="53" beanClass="com.install4j.runtime.beans.groups.HorizontalFormComponentGroup">
<serializedBean>
<property name="alignFirstLabel" type="boolean" value="false" />
<property name="insets">
<object class="java.awt.Insets">
<int>3</int>
<int>5</int>
<int>8</int>
<int>5</int>
</object>
</property>
</serializedBean>
<beans>
<formComponent id="54" beanClass="com.install4j.runtime.beans.formcomponents.SpringComponent" />
<formComponent name="Back button" id="55" beanClass="com.install4j.runtime.beans.styles.StandardControlButtonComponent">
<serializedBean>
<property name="buttonText" type="string">&lt; ${i18n:ButtonBack}</property>
<property name="controlButtonType" type="enum" class="com.install4j.api.context.ControlButtonType" value="PREVIOUS" />
</serializedBean>
</formComponent>
<formComponent name="Next button" id="56" beanClass="com.install4j.runtime.beans.styles.StandardControlButtonComponent">
<serializedBean>
<property name="buttonText" type="string">${i18n:ButtonNext} &gt;</property>
<property name="controlButtonType" type="enum" class="com.install4j.api.context.ControlButtonType" value="NEXT" />
</serializedBean>
</formComponent>
<formComponent name="Cancel button" id="57" beanClass="com.install4j.runtime.beans.styles.StandardControlButtonComponent" insetLeft="5">
<serializedBean>
<property name="buttonText" type="string">${i18n:ButtonCancel}</property>
<property name="controlButtonType" type="enum" class="com.install4j.api.context.ControlButtonType" value="CANCEL" />
</serializedBean>
</formComponent>
</beans>
</group>
</formComponents>
</style>
</beans>
</group>
</styles>
</installerGui>
<mediaSets>
<windows name="Windows" id="60">
<jreBundle jreBundleSource="generated">
<modules>
<module name="java.scripting" />
</modules>
</jreBundle>
</windows>
<macos name="macOS Single Bundle" id="159" launcherId="59">
<jreBundle jreBundleSource="preCreated" includedJre="macos-amd64-11.0.6" />
</macos>
</mediaSets>
</install4j>

@ -1,17 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>OpenRocket Test Libraries</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>OpenRocket Test Libraries</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

@ -0,0 +1 @@
open_collective: openrocket

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save