MoI discussion forum
MoI discussion forum

Full Version: NACA Airfoil script

Show messages:  1-5  6-25  26-31

From: Hamish Mead (HAIRYKIWI)
21 Feb 2015   [#6]
Here's the first release of the NACA Airfoil Generating script :)



Release notes copied here for convenience:

REVISION HISTORY
DATE CHANGES
2015-02-21 Initial ALPHA release.

RELEASE NOTE:
This version only generates a NACA five-digit series airfoil and
the associated airfoil mean chord line. Output has NOT YET BEEN VERIFIED
against official NACA ordinates available in the pdf documents below.

KNOWN LIMITATIONS:
- T.E. currently only created as in the 'open' style (as described by NACA).
A line segment closes the otherwise open T.E., however it and the airfoil
profile are not joined by the script, (for want of MoI geometry database
method knowledge); do it manually for the meantime if required.
- If coefficient A4 were to be edited to generate a closed T.E., the
T.E. shape is incorrect. (as permitted by NACA documentation)
TODO: make closed T.E. curve start(?) and endpoints corner points.
TODO: make T.E. thickness user variable (var A4).
- Reflex camber lines are not yet implemented.
- TODO: Implement four-digit series, 43012A, six-digit series; in roughly
that order.


I got a little distracted playing with hiding/unhiding divs in the UI (to enable separate four-digit and five-digit series UIs). It only partially worked, so I returned the htm to an earlier version for the moment.

I also played with joining a line segment to a curve, before each is committed - it's not working yet - I just don't have a grasp on the construct of a GeometryFactory vs a GeometryDatabase.
I got stuck trying to get (convert?) the ObjectList objects from an interpcurve factory into a GeomObject object for the join factory. I'm not sure it's even possible, or a correct approach.

Brian - you experienced similar problems with your prop generating script: http://moi3d.com/forum/index.php?webtag=MOI&msg=4801.159 - but I can't see how you implemented the methods from the SpurGearProfile in PropDesignGeoThru_1_7_2012.7z - if that even is the version in which you got the join working.

The ideal solution would actually be to forget about a join and simply make the first and last points corner points. Is it even possible to specify that points in a GeometryFactory are corner points? I need the last point of the airfoil curve to be a corner point in any case, if the airfoil profile is to be a closed one. Equally, there would be two corner points if I was to close the otherwise open, (NACA terminology for a trailing edge (T.E.) edge with finite thickness) trailing edge with a line segment.

I also found some potentially useful extra methods not yet documented in David Morrill's 'Moment of Inspiration Javascript Documentation' in the moi.idl file:
[GeometryFactory].getInputObjects() and [GeometryFactory].getCreatedObjects() - are these of any use or am I barking up the wrong tree? Where might they be used anyway?

Thanks for any further help or comments - and please tell me about any bugs (I expect many).

BTW, if you're not into building wings, some of the thicker profiles this script generates make a good budgerigar-like profile for further lofting.

Cheers,
Hamish

Attachments:
NACAAirfoilGenerator-2015-02-21.zip

Image Attachments:
NACAAirfoilGenerator-2015-02-21-800px.png 


From: Frenchy Pilou (PILOU)
21 Feb 2015   [#7]
French Version ;)
http://moiscript.weebly.com/aile-naca.html


From: Michael Gibson
21 Feb 2015   [#8] In reply to [#6]
Hi Hamish, some great progress!

> I also played with joining a line segment to a curve, before each is committed - it's not
> working yet - I just don't have a grasp on the construct of a GeometryFactory vs a
> GeometryDatabase.
> I got stuck trying to get (convert?) the ObjectList objects from an interpcurve factory into
> a GeomObject object for the join factory. I'm not sure it's even possible, or a correct approach.

One thing you might be running into is if a factory does asynchronous object generation (meaning it actually does its calculation in a separate moi_commandprocessor.exe process, generally used for possibly long running calculations) the inputs you give to it need to be active in the geometry database and not a "loose object" that has just been dynamically created but not added to the geometry database yet. You get a "loose object" if you use factory.calculate() to generate it. These objects currently have to be added in to the geometry database in order for them to be used as inputs to an async factory and Join is one of these types of factories. I'd like to change how this works in the future so as not to have this requirement but it will take some work since some parts of object serialization and deserialization are based off of a unique object id number that is set when objects get added to the geometry database.


> I just don't have a grasp on the construct of a GeometryFactory vs a GeometryDatabase.

A GeometryFactory is something that you use to generate objects, it has inputs that can be set on it, and then for regular commands a call to factory.update() will cause the factory to generate objects and put them in the GeometryDatabase. The GeometryDatabase is not something you create yourself, it's basically the master list of all objects in the model, for example when the screen draws it's every object in the GeometryDatabase that gets drawn.

> [GeometryFactory].getInputObjects() and [GeometryFactory].getCreatedObjects() - are these of any
> use or am I barking up the wrong tree? Where might they be used anyway?

You can call these if you use factory.update() - the call to factory.update() will generate objects and put them into the GeometryDatabase automatically, if you then want to get a hold of an object list of what was actually generated then the .getCreatedObjects() will do that.


Most things in the current scripting environment are heavily oriented towards creating things in the same way as a regular command would, basically by setting some options and then having the objects show up on screen, so usually a regular MoI command just calls factory.update() and does not deal with the generated objects directly itself after that.

- Michael
From: bemfarmer
22 Feb 2015   [#9] In reply to [#8]
I'll be looking at the script over the next few days...

- Brian
From: Hamish Mead (HAIRYKIWI)
23 Feb 2015   [#10]
Hi Guys,

Pilou - merci beaucoup! :)

Brian - Thanks for taking a look.

Michael, Thanks for your explanations - that's helped a lot, conceptually.

As for putting it into practise, I'm still missing something.

I tried:
code:
var objectstojoin = moi.geometryDatabase.createObjectList();
objectstojoin.addObject( FactoryAirfoil.update().getCreatedObjects() );
objectstojoin.addObject( FactoryLine.update().getCreatedObjects() );
var FactoryJoin = moi.command.createFactory( 'join' );
FactoryJoin.setInput( 0, objectstojoin );


This was the result:



In future, can I somehow capture the MoI javascript error code as text instead of a screen capture?

Cheers,
Hamish

Edit: code now in code block

Image Attachments:
naca-airfoil-generator-error201502231123.png 


From: ttype (STRUBE)
23 Feb 2015   [#11] In reply to [#10]
I don't know if it works for your script, but do you know this very simple script console?

https://sites.google.com/site/nakanosoramemo/software/moi3d/script-console
From: Hamish Mead (HAIRYKIWI)
23 Feb 2015   [#12] In reply to [#11]
Hi ttype,
Thanks! That's definitely faster for testing parts of a script.

- Hamish
From: Max Smirnov (SMIRNOV)
23 Feb 2015   [#13] In reply to [#12]
Hi Hamish,

>>objectstojoin.addObject( FactoryAirfoil.update().getCreatedObjects() );
You are trying to use ObjectList instead of Object.

var objects = FactoryAirfoil.update().getCreatedObjects();
for (var i=0; i<objects.length; i++) objectstojoin.addObject(objects.item(i));
From: Hamish Mead (HAIRYKIWI)
23 Feb 2015   [#14] In reply to [#13]
Thanks Max!

Conceptually that's really helpful, but now the .update() method returns nothing usable. so I tried:

var objectlist = FactoryAirfoil.calculate().getCurves(); // should return an objectlist of curve items within the objectlist returned by the .calculate???
for (var i=0; i<objectlist.length; i++) objectstojoin.addObject(objectlist.item(i));

Now no error is thrown - but also there is no output - but I'm in a rush.

Will have time to look into it later today.

Cheers,
Hamish
From: Michael Gibson
23 Feb 2015   [#15] In reply to [#14]
Hi Hamish, to put in a code block here in the forum use <code></code> make sure you're not using something like [code] instead.

re:
> objectstojoin.addObject( FactoryAirfoil.update().getCreatedObjects() );
> objectstojoin.addObject( FactoryLine.update().getCreatedObjects() );

The problem here is factory.update() does not return anything directly itself, it just causes the geometry factory to calculate the objects and update the factory's own internal lists of objects for what was created. If you then want to get at those created objects you need to call factory.getCreatedObjects().

That's different than factory.calculate() - calling factory.calculate() does directly return an object list to the caller and generates "loose objects" which are not yet part of the geometry database main object list of objects to draw and save in the file and so forth.

So your code would need to be changed to have the .update call on a previous line before you call factory.getCreatedObjects(), something like this instead (and also be modified to deal with the ObjectList that is returned from getCreatedObjects(), you are treating it as a single object being returned rather than an object list), something like:

FactoryAirfoil.update();
var objectlist = Factory.getCreatedObjects();
for ( var i = 0; i < objectlist.length; i++ ) objectstojoin.addObject( objectlist.item(i) );

- Michael
From: bemfarmer
23 Feb 2015   [#16] In reply to [#14]
Hi Hamish,

There is some Joining done in the chain script, and more recently in the _elastica2 script.

- Brian
From: Hamish Mead (HAIRYKIWI)
23 Feb 2015   [#17] In reply to [#15]
Hi Michael,

Thanks for your suggestions and further explanations.

In a hurry, I was using <code><\code> - i.e. wrong slash direction. :/

I found the .update() .getCreatedObjects() approach you suggested 'sort of works', but leaves 'orphaned display objects'; see my note at the end of the first code block below.

Here's are three 'Join Two Line Segment' examples (can be copy pasted into the script console that ttype mentioned earlier):
Partially working code:
var line_a = moi.command.createFactory( 'line' );
line_a.setInput( 0, moi.vectorMath.createPoint( 0, 0, 0 ));
line_a.setInput( 1, moi.vectorMath.createPoint( 1, 1, 0 ));
line_a.update();
var objectlist_a = line_a.getCreatedObjects();

var line_b = moi.command.createFactory( 'line' );
line_b.setInput( 0, moi.vectorMath.createPoint( 0, 0, 0 ));
line_b.setInput( 1, moi.vectorMath.createPoint( 1, -1, 0));
line_b.update();
var objectlist_b = line_a.getCreatedObjects();

var objectstojoin = moi.geometryDatabase.createObjectList();
for ( var i = 0; i < objectlist_a.length; i++ ) objectstojoin.addObject( objectlist_a.item(i));
for ( var i = 0; i < objectlist_b.length; i++ ) objectstojoin.addObject( objectlist_b.item(i));

moi.geometryDatabase.addobjects(objectstojoin);

var factoryjoin_ab = moi.command.createFactory( 'join' );
factoryjoin_ab.setInput( 0, objectstojoin );
factoryjoin_ab.commit();


//  line_a.update() and line_b.update() displays those objects, but of course doesn't commit them,
//  leaving 'orphaned display objects' visible: i.e. objects that are displayed, but never selectable after the script completes.


In the end I discovered that using the factory.calculate().item() approach - without using .getCreatedObjects() - does actually work as required.
Here are two examples:

Working code:
var line_a = moi.command.createFactory( 'line' );
line_a.setInput( 0, moi.vectorMath.createPoint( 0, 0, 0 ));
line_a.setInput( 1, moi.vectorMath.createPoint( 1, 1, 0 ));
var line_a_objectlist = line_a.calculate();

var line_b = moi.command.createFactory( 'line' );
line_b.setInput( 0, moi.vectorMath.createPoint( 0, 0, 0 ));
line_b.setInput( 1, moi.vectorMath.createPoint( 1, -1, 0 ));
var line_b_objectlist = line_b.calculate();

var objectstojoin = moi.geometryDatabase.createObjectList();
for ( var i = 0; i < line_b_objectlist.length; i++ ) objectstojoin.addObject(line_a_objectlist.item(i));
for ( var i = 0; i < line_b_objectlist.length; i++ ) objectstojoin.addObject(line_b_objectlist.item(i));

moi.geometryDatabase.addobjects(objectstojoin);

var factoryjoin_ab = moi.command.createFactory( 'join' );
factoryjoin_ab.setInput( 0, objectstojoin );
factoryjoin_ab.commit();

// Notes:
// .item(i) returns the i'th GeomObject object
// .calculate() returns an ObjectList of objects
// .addobject ONLY takes a GeomObject object
// .addobjects ONLY takes an objectlist



Working code:
var line_a = moi.command.createFactory( 'line' );
line_a.setInput( 0, moi.vectorMath.createPoint( 0, 0, 0 ));
line_a.setInput( 1, moi.vectorMath.createPoint( 1, 1, 0 ));

var line_b = moi.command.createFactory( 'line' );
line_b.setInput( 0, moi.vectorMath.createPoint( 0, 0, 0 ));
line_b.setInput( 1, moi.vectorMath.createPoint( 1, -1, 0 ));

var objectstojoin = moi.geometryDatabase.createObjectList();

objectstojoin.addObject(line_a.calculate().item(0));
objectstojoin.addObject(line_b.calculate().item(0));

moi.geometryDatabase.addobjects(objectstojoin);

var factoryjoin_ab = moi.command.createFactory( 'join' );
factoryjoin_ab.setInput( 0, objectstojoin );
factoryjoin_ab.commit();

// Notes:
// .item(i) returns the i'th GeomObject object
// .calculate() returns an ObjectList of objects
// .addobject ONLY takes a GeomObject object
// .addobjects ONLY takes an objectlist


I'll update the NACA Airfoil script when I get a spare moment.

Good night, and thank you all your help :)

- Hamish
From: Hamish Mead (HAIRYKIWI)
23 Feb 2015   [#18] In reply to [#16]
Thanks Brian. The more scripts to review the better!
From: Michael Gibson
23 Feb 2015   [#19] In reply to [#17]
Hi Hamish,

> I found the .update() .getCreatedObjects() approach you suggested 'sort of works', but leaves
> 'orphaned display objects'; see my note at the end of the first code block below.

You could try putting in a call to factory.cancel(); to have the factory remove the created objects.

But it sounds like you already have a solution!

- Michael
From: Hamish Mead (HAIRYKIWI)
24 Feb 2015   [#20] In reply to [#19]
Hi Michael,

Yeah, I did try factory.cancel() , factory.reset() and even factory.removeLastInput() but none of those methods removed the intermediate objects.

Cheers,
Hamish
From: Hamish Mead (HAIRYKIWI)
23 Mar 2015   [#21]
Here's the latest NACAAirfoilGenerator script with various minor and a few major improvements since first release:



RELEASE NOTES:
- Now generates all 'basic' NACA four-digit and five-digit series airfoils, including 43012A.
- Variable thickness trailing edge (T.E) implemented.
- Zero T.E. thickness airfoils now draw correctly.
- Conformity of output with official NACA ordinates has been verified* for NACA 0012, 6518, 23012, 43012 & 43012A, see file:
NACAAirfoilGenerator ordinates vs airfoils-2015-03-23.3dm in the attached zip.

* "verified" is probably not the best word, as errors are known to exist in the original NACA ordinate data. As you can see though, output from the script appears to be a reasonable match to the ordinates for the above mentioned airfoils at least:



KNOWN LIMITATIONS:
- Five-digit airfoils with reflex camber lines are not yet implemented.
CAUTION:
A4 coefficient (slider) value input can be set by user 'out of NACA limits'.
- Input parameter validation is rudimentary where it has been implemented.
- TODO: Implement four-digit modified, five-digit modified, and six-digit series - http://m-selig.ae.illinois.edu/ads/naca980820.bas contains working (public domain) code likely worth incorporating.

Generating airfoils with less than 60 chord-wise stations is not recommended as the airfoil's curvature smoothness, when checked with a curvature analysis tool, reduces noticeable. Conversely, generating more than 100 stations doesn't appear to yield much if any noticeable improvement.

I'll make a post about how the thickness distribution curve for the 43012A was generated with an additional reverse-action script another day. That kept me pretty busy for quiet a while.

As ever, any feedback - especially bug reports - is always appreciated.

- Hamish

Attachments:
NACAAirfoilGenerator ordinates vs airfoils-2015-03-23.zip
NACAAirfoilGenerator-2015-03-23.zip

Image Attachments:
'NACAAirfoilGenerator ordinates vs airfoils-2015-03-23.png  NACAAirfoilGenerator-2015-03-23.PNG 


From: Hans
26 Mar 2015   [#22]
Hi Hamish

Thank you for the NACA skript that you have made. It is exactly what I need for a real aircraft projekt that I plane to build in my
comming reteirement. (NACA 23012)
Since a longer time I know that moi has a big potential as cad program for aircraft development. Not only for curvatures also for
prepairing structures for framework analysis. Together with a friend - because I have no clue in programming - we tryed to handle with lines and points to get koordinates and a sorting of lines to the right points. Short to say: at the end we have been not succesfull.
The goal was to get a .txt file from moi to make an input file for the FEA programm Z88 from the university of Bayreuth/Germany.
If you or someone other of the experienced programmer would like to have an overlook on this thema I would like to prepair all the files
you need to see what is the way of programming.

As you can read english is not my native language so it needs a longer time for me to prepairing my messages.

For the first is here the adress you can have an impression of the FEA analysis programm.

www.z88.de

There are two FEA programms for free. Both are with with all handbooks and tutorials also in english and realy worth to have a closer look.
Specialy Z88 Aurora.

With a positive answer of interest I start to prepaire the example files.

In every case I thank you again for the airfoil skript.

Hans
From: Hamish Mead (HAIRYKIWI)
27 Mar 2015   [#23] In reply to [#22]
Hi Hans,

It's a pleasure - and great to know the script might also be used by someone else. :)

I'd be very interested in taking a look at what you're trying to do to combine output from MoI with the open source z88 FEA software. z88 looks really interesting! I know only a little about FEA, but always wanted to learn more. I am just starting to build an aircraft from plans - a Corby CJ-1 'Starlet'. It uses the 43012A airfoil, hence my determination to do a nice job scripting it.

I'd describe myself only as a novice programmer, with interest + determination + internet connection for self-improvement. As such, if your requirements are beyond my current abilities, I'm sure there's enough scripting experience among the forum members to achieve what you need. I think what you're trying to achieve is potentially very interesting to lots more people, so hopefully there will be no shortage of interest in helping.

I would suggest though, that you start another discussion specific to the new script you want to see created - just to keep things relevant and possibly easier for other people to find.

Here's a photo of the award-winning Starlet my friend built (and my lovely wife):


- Hamish

Image Attachments:
gilse_heather_dymock_20120929_75pc.png 


From: Frenchy Pilou (PILOU)
27 Mar 2015   [#24]
No possible passenger in this cuty plane ?
From: Hamish Mead (HAIRYKIWI)
28 Mar 2015   [#25] In reply to [#24]
'fraid not Pilou - just one person and all the glorious blue sky they can eat ...maybe with cake and coffee at a neighbouring field for desert. ;)

- Hamish

Show messages:  1-5  6-25  26-31