Macro Airfoil Import & Scale
| Popis |
|---|
| Trace the perimeter of a Airfoil from a .dat file. Version macro : 2.1.2 Date last modification : 2019-07-16 FreeCAD version : All Download : ToolBar Icon Autor: quick61 |
| Autor |
| quick61 |
| Download |
| ToolBar Icon |
| Odkazy |
| Makro recepty| Jak nainstalovat makra Jak přizpůsobit panely nástrojů |
| Verze |
| 2.1.2 |
| Datum poslední úpravy |
| 2019-07-16 |
| Verze FreeCAD |
| All |
| Výchozí zástupce |
| None |
| Viz též |
| None |
Description
Popis
Toto makro při spuštění nejprve poskytne uživateli souborový prohlížeč, který vyhledá a vybere textový soubor profilu dat .dat. Po zvolení se zadá délka akordů a po stisknutí tlačítka OK se vytvoří správně měřítko profilu. K dispozici jsou zde dvě verze. Verze 1.5 by měla pracovat na verzích FreeCADu, 0.13 stabilních i všech verzích 0.14. Verze 2 by měla být použita pouze s verzemi FreeCAD rovnajícími se nebo vyššími než 0.14 3077 a bude fungovat nejlépe s verzemi vytvořenými s verzemi OCE / OCC verze 6.7 nebo vyšší.
See also Common Airfoil Data Import
Enter Chord Length
Zadejte délku chordu
Po výběru souboru profilu se objeví nové dialogové okno s žádostí o délku akordů. Může být zadána libovolná délka, v milimetrech. Po zadání požadované délky vytvoří makro předběžný vodič (DWire) podle bodů popsaných v dříve vybraném souboru profilu .dat v měřítku, které jste zadali pro délku akordy.
Select The File
After configuration user with a file browser that will allow you to select the desired airfoil .dat file. Browse to where you have saved the airfoil file, select it and press Open.
Airfoil selected
If the airfoil has been selected in the 3D view, run the macro and the Save is available in the dialog.
Airfoil saved
For save the naca profile, select the profile and run the macro
If the Save is checked the file window appear
Save
Specify the name of file.
The file is saved with 150 points of definition and not verify if the length of the airfoil follow the NACA rulles (length 1 mm)
For change the definition value go to:
Tools → Edit parameter... "BaseApp/Preferences/Macros/Airfoil_Import_and_Scale" then modify the numberCut value
The file is saved in the format "Title and coordinates X Y separate by coma".
Create sketch
If the Create Sketch is checked one sketch is created of the profile
If the profile is thickness the two profiles are created in a single sketch
Makra
Macro_Airfoil_Import_&_Scale.FCMacro
# This Macro, when run, will first provide the user with a file browser to##:Bookmark line 1
# locate and select a .dat airfoil text file. Once selected, a chord length is
# entered and upon pressing the OK button, a properly scaled airfoil is
# produced. There are two versions provided here. Version 1.5 should work on
# FreeCAD versions, 0.13 stable as well as all 0.14 versions. Version 2 should
# only be used with FreeCAD versions equal to or greater than 0.14 3077 and
# will work best with versions built with OCE/OCC versions 6.7 or greater (See
# the Wiki page for all available version).
#
# (c) quick61
__Name__ = 'Airfoil Import and Scale'
__Comment__ = 'Imports and scales an Airfoil in the form of a Draft Wire (DWire) or Basic Spline (BSpline)'
__Author__ = "quick61"
__Version__ = '3.1.0'
__Date__ = '2026-05-19'
__License__ = 'CC-BY-3.0'
__Web__ = "https://forum.freecad.org/viewtopic.php?f=22&t=5554"
__Wiki__ = "https://www.freecad.org/wiki/Macro_Airfoil_Import_%26_Scale"
__Icon__ = 'https://www.freecad.org/wiki/images/0/0c/Macro_Airfoil_Import_%26_Scale.png'
__Help__ = ''
__Naca__ = "http://airfoiltools.com/airfoil/index"
__Status__ = 'stable'
__Requires__ = 'Freecad >= 0.14.3706'
__Communication__ = ''
__Files__ = ''
import FreeCAD as app
import FreeCADGui as Gui
import PySide
from PySide import QtCore, QtGui
from PySide.QtGui import QLineEdit, QRadioButton
import Draft
import Part
import importAirfoilDAT
import os
# Select .dat airfoil data file to be imported
# PySide returns a tuple (filename, filter) instead of just a string like in PyQt
global filename
global nameFile
class AirfoilImporterAndScaler():
def __init__(self):
self.dialog = None
self.s1 = None
# Make dialog box and get the scale size
self.dialog = QtGui.QDialog()
self.dialog.resize(600,200)
self.dialog.setWindowTitle("Airfoil Import & Scale")
la = QtGui.QVBoxLayout(self.dialog)
t1 = QtGui.QLabel("Chord length")
la.addWidget(t1)
self.s1 = QtGui.QDoubleSpinBox()
self.s1.setDecimals(5)
self.s1.setMinimum(-9999999.9999999)
self.s1.setMaximum(9999999.9999999)
self.s1.setSuffix(" mm (length)")
self.s1.setValue(200.0)
la.addWidget(self.s1)
# Make dialog box and get sheeting thickness
t2 = QtGui.QLabel("Sheeting thickness")
la.addWidget(t2)
self.s2 = None
self.s2 = QtGui.QDoubleSpinBox()
self.s2.setDecimals(2)
self.s2.setMinimum(0)
self.s2.setMaximum(9.99)
self.s2.setSuffix(" mm (Sheeting Thickness, a negative 2D offset)")
self.s2.setValue(0.0)
la.addWidget(self.s2)
####
self.FreeCAD_ParamGetSet = FreeCAD.ParamGet(u"User parameter:BaseApp/Preferences/Macros/Airfoil_Import_and_Scale")
self.FreeCAD_ParamGetSet.SetString(u"Version", __Version__ + " (" + __Date__ + ")")
self.numberCut = self.FreeCAD_ParamGetSet.GetInt("numberCut", 150) # number of coordinates
self.FreeCAD_ParamGetSet.SetInt("numberCut", self.numberCut)
####
# Add radio buttons to select between DWire and BSpline
self.radio1 = QtGui.QRadioButton("Make DWire")
self.radio2 = QtGui.QRadioButton("Make BSpline")
#Skip the Save button
self.radio3 = QtGui.QRadioButton("Save the selected airfoil")
#self.radio3.setVisible(False)
# set default to DWire & make radio buttons - Change self.radio1.setChecked(True) to
# self.radio2.setChecked(True) to set BSpline as default
la.addWidget(self.radio1)
self.radio1.setToolTip("Create DWire Airfoil")
la.addWidget(self.radio2)
self.radio2.setToolTip("Create BSplinee Airfoil")
self.radio2.setChecked(True)
#### save button
la.addWidget(self.radio3)
self.numberCut = self.FreeCAD_ParamGetSet.GetInt("numberCut") # number of coordinates
self.radio3.setToolTip(u"Only available if one Airfoil to save is selected" + "\n"
u"The actual value of definition is " + str(self.numberCut) + " points" + "\n"
u"For change this value, go to" + "\n"
u"User parameter:BaseApp/Preferences/Macros/Airfoil_Import_and_Scale" + "\n"
u"Change the 'numberCut' value")
self.radio3.setEnabled(False)
selected = ""
selected = FreeCADGui.Selection.getSelection()
if len(selected) != 0:
self.radio3.setEnabled(True)
self.CB01 = QtGui.QCheckBox()
self.CB01.setText(u"Create Sketch")
la.addWidget(self.CB01)
####
# Add OK / Cancel buttons
okbox = QtGui.QDialogButtonBox(self.dialog)
okbox.setOrientation(QtCore.Qt.Horizontal)
okbox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
la.addWidget(okbox)
QtCore.QObject.connect(okbox, QtCore.SIGNAL("accepted()"), self.proceed)
QtCore.QObject.connect(okbox, QtCore.SIGNAL("rejected()"), self.close)
QtCore.QMetaObject.connectSlotsByName(self.dialog)
self.dialog.show()
self.dialog.exec()
def proceed(self):
global filename
global nameFile
param = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro")# macro path
macroPath = param.GetString("MacroPath","") + "/" # macro path
filePath = ""
filePath = self.FreeCAD_ParamGetSet.GetString(u"filePath", filePath)
filePath = filePath.replace(u"\\","/") # convert the "\" to "/"
if filePath == "":
filePath = self.FreeCAD_ParamGetSet.GetString(u"filePath", macroPath)
if self.radio1.isChecked() or self.radio2.isChecked():
OpenName, filefilter = QtGui.QFileDialog.getOpenFileName(None, "Open An Airfoil File", filePath, "*.dat")
if OpenName != "":
####new2
pathFile = os.path.dirname(OpenName) + "/" #1# = C:/Provisoire400/
racineDrive = os.path.splitdrive(OpenName)[0] #2# = C:
formatFichier = os.path.splitext(OpenName)[1] #3# = .png
OpenName = os.path.splitext(OpenName)[0] #4# = /home/kubuntu/.FreeCAD/Macro/Texture_007_H #= C:/Provisoire400/image3D
nameFile = os.path.basename(OpenName) #5# = image3D
SaveNameformatFichier = OpenName + formatFichier #6# = C:/Provisoire400/image3D.png
pathFileSaveNameformatFichier = pathFile + nameFile + formatFichier #7# = C:/Provisoire400/image3D.png
####new2
self.FreeCAD_ParamGetSet.SetString("filePath", pathFile)
if self.radio1.isChecked():
try:
# This produces a scaled Airfoil with a DWire
scalefactor=self.s1.value()
f1=SaveNameformatFichier
importAirfoilDAT.insert(f1,"Unnamed")
points = FreeCAD.ActiveDocument.Wire
nacaDWire = Draft.scale([points], scale=FreeCAD.Vector(scalefactor,scalefactor,scalefactor), center=FreeCAD.Vector(0.0, 0.0, 0.0), copy=True)
nacaDWire.MakeFace = False
nacaDWire.Label = nameFile + "_(DWire)(" + str(scalefactor) + ")"
if self.s2.value() > 0:
# https://wiki.freecad.org/Draft_BSpline
# https://wiki.freecad.org/Draft_Scale
# https://wiki.freecad.org/Draft_Offset
# https://wiki.freecad.org/Vector_API
# http://airfoiltools.com/airfoil/index, .dat file format
# x 0.0 to 1.0, y -1.0 to +1.0
thickNess = self.s2.value()
print("Offset2D thickNess used is ", -thickNess)
try:
f = App.ActiveDocument.addObject("Part::Offset2D", "Offset2D")
f.Source = nacaDWire
f.Value = thickNess
f.Mode = "Skin"
f.Join = "Arc"
f.Intersection = True
f.Label = nameFile + "_(DWire)(" + str(scalefactor) + " offset2D -" + str(thickNess) + ")"
if self.CB01.isChecked():
sk = Draft.make_sketch([f, nacaDWire], autoconstraints=True)
sk.Label = nameFile + "_(DWire Sketch)(" + str(scalefactor) + ")"
App.ActiveDocument.recompute()
except Exception:
app.Console.PrintError("Error, offset2D handling\n")
else:
if self.CB01.isChecked():
sk = Draft.make_sketch([nacaDWire], autoconstraints=True)
sk.Label = nameFile + "_(DWire Sketch)(" + str(scalefactor) + ")"
App.ActiveDocument.recompute()
try:
App.getDocument('Unnamed').removeObject(nameFile)
App.getDocument('Unnamed').removeObject("Wire")
App.getDocument('Unnamed').recompute()
except Exception:
None
App.activeDocument().recompute(None,True,True)
except Exception:
app.Console.PrintError("Error, not a valid .dat file\n")
if self.radio2.isChecked():
try:
# This produces a scaled Airfoil with a BSpline
scalefactor=self.s1.value()
f1=SaveNameformatFichier
importAirfoilDAT.insert(f1,"Unnamed")
points = FreeCAD.ActiveDocument.Wire.Points
bspline = Draft.make_bspline(points, closed=True)
App.getDocument('Unnamed').recompute()
nacaBSpline = Draft.scale(bspline, scale=FreeCAD.Vector(scalefactor,scalefactor,scalefactor), center=FreeCAD.Vector(0.0, 0.0, 0.0), copy=True)
nacaBSpline.MakeFace = False
nacaBSpline.Label = nameFile + "_(BSpline)(" + str(scalefactor) + ")"
if self.s2.value() > 0:
# https://wiki.freecad.org/Draft_BSpline
# https://wiki.freecad.org/Draft_Scale
# https://wiki.freecad.org/Draft_Offset
# https://wiki.freecad.org/Vector_API
# http://airfoiltools.com/airfoil/index, .dat file format
# x 0.0 to 1.0, y -1.0 to +1.0
thickNess = self.s2.value()
print("Offset2D thickNess used is ", -thickNess)
try:
f = App.ActiveDocument.addObject("Part::Offset2D", "Offset2D")
f.Source = nacaBSpline
f.Value = -thickNess
f.Mode = "Skin"
f.Join = "Arc"
f.Intersection = True
f.Label = nameFile + "_(BSpline)(" + str(scalefactor) + " offset2D -" + str(thickNess) + ")"
App.ActiveDocument.recompute()
if self.CB01.isChecked():
sk = Draft.make_sketch([f, nacaBSpline], autoconstraints=True)
sk.Label = nameFile + "_(BSpline Sketch)(" + str(scalefactor) + ")"
App.ActiveDocument.recompute()
except Exception:
app.Console.PrintError("Error, offset2D handling\n")
else:
if self.CB01.isChecked():
sk = Draft.make_sketch([nacaBSpline], autoconstraints=True)
sk.Label = nameFile + "_(BSpline)(" + str(scalefactor) + ")"
App.ActiveDocument.recompute()
try:
App.getDocument('Unnamed').removeObject(nameFile)
App.getDocument('Unnamed').removeObject("Wire")
App.getDocument('Unnamed').removeObject(bspline.Name)
except Exception:
None
App.activeDocument().recompute(None,True,True)
except Exception:
app.Console.PrintError("Error, not a valid .dat file\n")
Gui.SendMsgToActiveView("ViewFit")
self.close() # close the window
if self.radio3 != None and self.radio3.isChecked():
SaveName, Filter = QtGui.QFileDialog.getSaveFileName(None, "Save An Airfoil File", filePath, "*.dat")
if SaveName != "":
####new2
pathFile = os.path.dirname(SaveName) + "/" #1# = C:/Provisoire400/
racineDrive = os.path.splitdrive(SaveName)[0] #2# = C:
formatFichier = os.path.splitext(SaveName)[1] #3# = .png
SaveName = os.path.splitext(SaveName)[0] #4# = /home/kubuntu/.FreeCAD/Macro/Texture_007_H #= C:/Provisoire400/image3D
nameFile = os.path.basename(SaveName) #5# = image3D
SaveNameformatFichier = SaveName + formatFichier #6# = C:/Provisoire400/image3D.png
pathFileSaveNameformatFichier = pathFile + nameFile + formatFichier #7# = C:/Provisoire400/image3D.png
####new2
self.FreeCAD_ParamGetSet.SetString("filePath", pathFile)
if "." in SaveNameformatFichier:
None
else:
SaveNameformatFichier += ".dat" # Mint
try:
selected = FreeCADGui.Selection.getSelection()[0]
pointsDirection = []
pointsDirection = selected.Shape.discretize(Number=self.numberCut) # discretize pour calculer la direction (avec un deuxieme point)
f = open(SaveNameformatFichier, 'w') # path to write
f.write("NACA" + nameFile + "\n") # title
for coor in pointsDirection:
f.write(" " + str(round(coor.x, 5)) + " " + str(round(coor.y, 5)) + "\n")
f.close() # close the file
except Exception:
app.Console.PrintError("Error, to Save .dat file\n")
self.close() # close the window
def close(self):
self.dialog.hide()
AirfoilImporterAndScaler()
Old versions
Jak používat - verze 1.5
Select The File
Vyberte soubor
Spuštění makra nejprve zobrazí uživateli prohlížeč souborů, který vám umožní vybrat požadovaný soubor datového souboru. Projděte si, kam jste uložili soubor profilu, vyberte jej a stiskněte Otevřít.

Enter Chord Length
Once the airfoil file has been selected, a new dialog will appear asking for a chord length. Any length may be entered, in millimeters. Once your desired length is entered, the Macro will produce a Draft Wire (DWire) following the points described in the previously selected .dat airfoil file at the scale you entered for the chord length.

Křídlový profil, správně měřítko, by nyní měl být ve vašem projektu připraven k použití.
How To Use - Version 2
Jak používat - verze 2
Volba souboru je stejná jako verze 1.5. S verzí 2 máte nyní možnost mít buď výsledný profil vytvořený pomocí DWire nebo Basic Spline (BSpline). Stejně jako u verze 1.5 zadáte požadovanou délku. Dále můžete vybrat, který typ fólie chcete. Stačí kliknout na přepínač BSpline nebo nechat jako výchozí DWire.

The Macros
Version 1.5
Macro_Airfoil_Import_&_Scale.FCMacro
# # # #
#
# AIRFOIL IMPORT & SCALE v1.5
#
# Imports and scales an Airfoil in the form of a Draft Wire (DWire)
#
# # # #
from PySide import QtCore, QtGui
from PySide.QtGui import QLineEdit
import FreeCAD, FreeCADGui, Draft
import importAirfoilDAT
# Select .dat airfoil data file to be imported
filename = QtGui.QFileDialog.getOpenFileName(QtGui.qApp.activeWindow(),'Open An Airfoil File','*.dat')
class p():
def proceed(self):
try:
# This produces a scaled Airfoil with a DWire
scalefactor=float(self.s1.text())
f1=str(filename)
importAirfoilDAT.insert(f1,"Unnamed")
Draft.scale(App.ActiveDocument.ActiveObject,delta=App.Vector(scalefactor,scalefactor,scalefactor),center=App.Vector(0,0,0),legacy=True)
except:
FreeCAD.Console.PrintError("Error, not a valid .dat file\n")
self.close()
def close(self):
self.dialog.hide()
def __init__(self):
self.dialog = None
self.s1 = None
# Make dialog box and get the scale size
self.dialog = QtGui.QDialog()
self.dialog.resize(350,100)
self.dialog.setWindowTitle("Airfoil Import & Scale")
la = QtGui.QVBoxLayout(self.dialog)
t1 = QtGui.QLabel("Chord Length")
la.addWidget(t1)
self.s1 = QtGui.QLineEdit()
la.addWidget(self.s1)
# Add OK / Cancel buttons
#ori okbox = QtGui.QDialogButtonBox(self.dialog)
#ori okbox.setOrientation(QtCore.Qt.Horizontal)
#ori okbox.setStandardButtons(QtGui.QDialogButtonBox.Cancel -PIPE- QtGui.QDialogButtonBox.Ok)
# modify original code for install with addon-install cause -PIPE- 05-12-2016 FC 0.16
okbox = QtGui.QDialogButtonBox(self.dialog)
okbox.setOrientation(QtCore.Qt.Horizontal)
okbox.setStandardButtons(QtGui.QDialogButtonBox.Ok)
cancelbox = QtGui.QDialogButtonBox(self.dialog)
cancelbox.setOrientation(QtCore.Qt.Horizontal)
cancelbox.setStandardButtons(QtGui.QDialogButtonBox.Cancel)
cancelbox.move(0,62)
la.addWidget(okbox)
QtCore.QObject.connect(okbox, QtCore.SIGNAL("accepted()"), self.proceed)
QtCore.QObject.connect(cancelbox, QtCore.SIGNAL("rejected()"), self.close)
QtCore.QMetaObject.connectSlotsByName(self.dialog)
self.dialog.show()
self.dialog.exec_()
p()
Version 2
# # # #
#
# AIRFOIL IMPORT & SCALE v2.
#
# Imports and scales an Airfoil in the form of a Draft Wire (DWire) or Basic Spline (BSpline)
#
# For FreeCAD Versions = or > 0.14 Revision 3077
#
# Works best with OCC/OCE = or > 6.7
#
# # # #
from PySide import QtCore, QtGui
from PySide.QtGui import QLineEdit, QRadioButton
import FreeCAD, FreeCADGui, Draft
import importAirfoilDAT
# Select .dat airfoil data file to be imported
filename = QtGui.QFileDialog.getOpenFileName(QtGui.qApp.activeWindow(),'Open An Airfoil File','*.dat')
class p():
def proceed(self):
if self.radio1.isChecked():
try:
# This produces a scaled Airfoil with a DWire
scalefactor=float(self.s1.text())
f1=str(filename)
importAirfoilDAT.insert(f1,"Unnamed")
Draft.scale(App.ActiveDocument.ActiveObject,delta=App.Vector(scalefactor,scalefactor,scalefactor),center=App.Vector(0,0,0),legacy=True)
except:
FreeCAD.Console.PrintError("Error, not a valid .dat file\n")
self.close()
if self.radio2.isChecked():
try:
# This produces a scaled Airfoil with a BSpline
scalefactor=float(self.s1.text())
f1=str(filename)
importAirfoilDAT.insert(f1,"Unnamed")
points = FreeCAD.ActiveDocument.ActiveObject.Points
Draft.makeBSpline(points, closed=True)
Draft.scale(App.ActiveDocument.ActiveObject,delta=App.Vector(scalefactor,scalefactor,scalefactor),center=App.Vector(0,0,0),legacy=True)
App.getDocument("Unnamed").removeObject("DWire")
except:
FreeCAD.Console.PrintError("Error, not a valid .dat file\n")
self.close()
def close(self):
self.dialog.hide()
def __init__(self):
self.dialog = None
self.s1 = None
# Make dialog box and get the scale size
self.dialog = QtGui.QDialog()
self.dialog.resize(350,100)
self.dialog.setWindowTitle("Airfoil Import & Scale")
la = QtGui.QVBoxLayout(self.dialog)
t1 = QtGui.QLabel("Chord Length")
la.addWidget(t1)
self.s1 = QtGui.QLineEdit()
la.addWidget(self.s1)
# Add radio buttons to select between DWire and BSpline
self.radio1 = QRadioButton("Make DWire")
self.radio2 = QRadioButton("Make BSpline")
# set default to DWire & make radio buttons - Change self.radio1.setChecked(True) to
# self.radio2.setChecked(True) to set BSpline as default
self.radio1.setChecked(True)
la.addWidget(self.radio1)
la.addWidget(self.radio2)
# Add OK / Cancel buttons
okbox = QtGui.QDialogButtonBox(self.dialog)
okbox.setOrientation(QtCore.Qt.Horizontal)
okbox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
la.addWidget(okbox)
QtCore.QObject.connect(okbox, QtCore.SIGNAL("accepted()"), self.proceed)
QtCore.QObject.connect(okbox, QtCore.SIGNAL("rejected()"), self.close)
QtCore.QMetaObject.connectSlotsByName(self.dialog)
self.dialog.show()
self.dialog.exec_()
p()
Version 2.1
Updated by mangtronix to use PySide instead of PyQt (used in older versions of FreeCAD).
# # # #
#
# AIRFOIL IMPORT & SCALE v2.1
#
# Imports and scales an Airfoil in the form of a Draft Wire (DWire) or Basic Spline (BSpline)
#
# For FreeCAD Versions = or > 0.14 Revision 3703
#
# Works best with OCC/OCE = or > 6.7
#
# # # #
from PySide import QtCore, QtGui
from PySide.QtGui import QLineEdit, QRadioButton
import FreeCAD, FreeCADGui, Draft
import importAirfoilDAT
# Select .dat airfoil data file to be imported
# PySide returns a tuple (filename, filter) instead of just a string like in PyQt
filename, filefilter = QtGui.QFileDialog.getOpenFileName(QtGui.qApp.activeWindow(),'Open An Airfoil File','*.dat')
class p():
def proceed(self):
global filename
if self.radio1.isChecked():
#if True:
try:
# This produces a scaled Airfoil with a DWire
scalefactor=float(self.s1.text())
f1=str(filename)
importAirfoilDAT.insert(f1,"Unnamed")
Draft.scale(App.ActiveDocument.ActiveObject,delta=App.Vector(scalefactor,scalefactor,scalefactor),center=App.Vector(0,0,0),legacy=True)
except Exception, e:
FreeCAD.Console.PrintError("Error, not a valid .dat file\n")
self.close()
if self.radio2.isChecked():
try:
# This produces a scaled Airfoil with a BSpline
scalefactor=float(self.s1.text())
f1=str(filename)
importAirfoilDAT.insert(f1,"Unnamed")
points = FreeCAD.ActiveDocument.ActiveObject.Points
Draft.makeBSpline(points, closed=True)
Draft.scale(App.ActiveDocument.ActiveObject,delta=App.Vector(scalefactor,scalefactor,scalefactor),center=App.Vector(0,0,0),legacy=True)
App.getDocument("Unnamed").removeObject("DWire")
except:
FreeCAD.Console.PrintError("Error, not a valid .dat file\n")
self.close()
def close(self):
self.dialog.hide()
def __init__(self):
self.dialog = None
self.s1 = None
# Make dialog box and get the scale size
self.dialog = QtGui.QDialog()
self.dialog.resize(350,100)
self.dialog.setWindowTitle("Airfoil Import & Scale")
la = QtGui.QVBoxLayout(self.dialog)
t1 = QtGui.QLabel("Chord Length")
la.addWidget(t1)
self.s1 = QtGui.QLineEdit()
la.addWidget(self.s1)
# Add radio buttons to select between DWire and BSpline
self.radio1 = QRadioButton("Make DWire")
self.radio2 = QRadioButton("Make BSpline")
# set default to DWire & make radio buttons - Change self.radio1.setChecked(True) to
# self.radio2.setChecked(True) to set BSpline as default
self.radio1.setChecked(True)
la.addWidget(self.radio1)
la.addWidget(self.radio2)
# Add OK / Cancel buttons
okbox = QtGui.QDialogButtonBox(self.dialog)
okbox.setOrientation(QtCore.Qt.Horizontal)
okbox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
la.addWidget(okbox)
QtCore.QObject.connect(okbox, QtCore.SIGNAL("accepted()"), self.proceed)
QtCore.QObject.connect(okbox, QtCore.SIGNAL("rejected()"), self.close)
QtCore.QMetaObject.connectSlotsByName(self.dialog)
self.dialog.show()
self.dialog.exec_()
p()
Version 2.1.2
Macro_Airfoil_Import_&_Scale.FCMacro
# This Macro, when run, will first provide the user with a file browser to
# locate and select a .dat airfoil text file. Once selected, a chord length is
# entered and upon pressing the OK button, a properly scaled airfoil is
# produced. There are two versions provided here. Version 1.5 should work on
# FreeCAD versions, 0.13 stable as well as all 0.14 versions. Version 2 should
# only be used with FreeCAD versions equal to or greater than 0.14 3077 and
# will work best with versions built with OCE/OCC versions 6.7 or greater (See
# the Wiki page for all available version).
#
# (c) quick61
__Name__ = 'Airfoil Import and Scale'
__Comment__ = 'Imports and scales an Airfoil in the form of a Draft Wire (DWire) or Basic Spline (BSpline)'
__Author__ = "quick61"
__Version__ = '2.1.2'
__Date__ = '2019-07-16'
__License__ = ''
__Web__ = "https://forum.freecad.org/viewtopic.php?f=22&t=5554"
__Wiki__ = "https://www.freecad.org/wiki/Macro_Airfoil_Import_%26_Scale"
__Icon__ = 'https://www.freecad.org/wiki/images/0/0c/Macro_Airfoil_Import_%26_Scale.png'
__Help__ = ''
__Status__ = 'stable'
__Requires__ = 'Freecad >= 0.14.3706'
__Communication__ = ''
__Files__ = ''
import FreeCAD as app
import PySide
from PySide import QtCore, QtGui
from PySide.QtGui import QLineEdit, QRadioButton
import Draft
import importAirfoilDAT
# Select .dat airfoil data file to be imported
# PySide returns a tuple (filename, filter) instead of just a string like in PyQt
global filename
global nameFile
try:
filename, filefilter = QtGui.QFileDialog.getOpenFileName(QtGui.qApp.activeWindow(), 'Open An Airfoil File', '*.dat')
except Exception:
param = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro")# macro path
path = param.GetString("MacroPath","") + "/" # macro path
filename, filefilter = PySide.QtGui.QFileDialog.getOpenFileName(None, "Open An Airfoil File", path, "*.dat")
nameFile = filename.split("/")[-1][:-4]
class AirfoilImporterAndScaler():
def __init__(self):
self.dialog = None
self.s1 = None
# Make dialog box and get the scale size
self.dialog = QtGui.QDialog()
self.dialog.resize(350,100)
self.dialog.setWindowTitle("Airfoil Import & Scale")
la = QtGui.QVBoxLayout(self.dialog)
t1 = QtGui.QLabel("Chord Length")
la.addWidget(t1)
self.s1 = QtGui.QLineEdit()
la.addWidget(self.s1)
# Add radio buttons to select between DWire and BSpline
self.radio1 = QtGui.QRadioButton("Make DWire")
self.radio2 = QtGui.QRadioButton("Make BSpline")
# set default to DWire & make radio buttons - Change self.radio1.setChecked(True) to
# self.radio2.setChecked(True) to set BSpline as default
self.radio1.setChecked(True)
la.addWidget(self.radio1)
la.addWidget(self.radio2)
# Add OK / Cancel buttons
okbox = QtGui.QDialogButtonBox(self.dialog)
okbox.setOrientation(QtCore.Qt.Horizontal)
okbox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
la.addWidget(okbox)
QtCore.QObject.connect(okbox, QtCore.SIGNAL("accepted()"), self.proceed)
QtCore.QObject.connect(okbox, QtCore.SIGNAL("rejected()"), self.close)
QtCore.QMetaObject.connectSlotsByName(self.dialog)
self.dialog.show()
self.dialog.exec_()
def proceed(self):
global filename
global nameFile
if self.radio1.isChecked():
try:
# This produces a scaled Airfoil with a DWire
scalefactor=float(self.s1.text())
f1=str(filename)
importAirfoilDAT.insert(f1,"Unnamed")
try:
Draft.scale(App.ActiveDocument.ActiveObject,delta=App.Vector(scalefactor,scalefactor,scalefactor),center=App.Vector(0,0,0),legacy=True)
except Exception:
Draft.scale(App.ActiveDocument.ActiveObject,scale=App.Vector(scalefactor,scalefactor,scalefactor),center=App.Vector(0.0,0.0,0.0),copy=False)
App.ActiveDocument.ActiveObject.Label = nameFile + "_(DWire)"
except Exception as e:
app.Console.PrintError("Error, not a valid .dat file\n")
if self.radio2.isChecked():
try:
# This produces a scaled Airfoil with a BSpline
scalefactor=float(self.s1.text())
f1=str(filename)
importAirfoilDAT.insert(f1,"Unnamed")
points = app.ActiveDocument.ActiveObject.Points
App.getDocument("Unnamed").removeObject(App.ActiveDocument.ActiveObject.Name)
Draft.makeBSpline(points, closed=True)
try:
Draft.scale(App.ActiveDocument.ActiveObject,delta=App.Vector(scalefactor,scalefactor,scalefactor),center=App.Vector(0,0,0),legacy=True)
except Exception:
for i in range(len(points)):
Draft.scaleVertex(App.ActiveDocument.ActiveObject, i, App.Vector(scalefactor,scalefactor,scalefactor), App.Vector(0.0,0.0,0.0))
App.ActiveDocument.ActiveObject.Label = nameFile + "_(BSpline)"
except:
app.Console.PrintError("Error, not a valid .dat file\n")
try:
# delete the directory created by importAirfoilDAT
for obj in App.ActiveDocument.Objects:
if (obj.TypeId == "App::DocumentObjectGroup") and (obj.Name == nameFile):
App.getDocument("Unnamed").removeObject(nameFile)
except Exception:
None
self.close() # close the window
def close(self):
self.dialog.hide()
AirfoilImporterAndScaler()
Odkaz
Diskuse o Forum
UIUC Applied Aerodynamics Group Departement of Aerospace Engineering






