MoI discussion forum
MoI discussion forum

Full Version: Rotate Array?

From: Whiteman Dynamic (TIM_WHITEMAN)
5 Mar 2020   [#1]
Hello MoI friends,

I am wondering if anyone can help me with a fairly simple, but seemingly complex request please?

I am trying to achieve a 2D task that I cannot achieve in Illustrator (but should be able to!) and have come very close to achieving what I want to achieve with MoI. I'm wondering if there was ever a script created that was similar to the existing "Scale Array"? What I need is exactly the same, but instead rotating each array instance by a certain degree angle. I have enclosed a screenshot of what I mean...



So I would like to Array 17 copies (18 total) of the initial blue leaf, with the final leaf matching the angle of the red leaf and the instances (black) morphing between the two. As you can see, I have got very close to what I am trying to achieve with Array Curve and Scale Array. I just need to be able to incrementally adjust the angle of the leaves in between to achieve the 18th leaf as the red leaf, instead of the green leaf.

I'm sorry if I have over-complicated that? I think my diagram should visually explain what I am trying to achieve?

Thanks as always and hopefully one of you bright geniuses will have an idea or a solution?

I did have a look at the two Scale Array files in the hope of adapting them to rotate instead of scale, but sadly it's slightly more advanced than I am capable.

Many thanks,

Tim

Image Attachments:
Example.jpg 


From: bemfarmer
5 Mar 2020   [#2] In reply to [#1]
Hi Tim
I think this is a math question.
Measure the angle of the blue leaf. Say 210 degrees.
Measure the angle of the red leaf. Say 70 degrees
Subtract to find the change in angle. ~ 140 degrees

Divide by 17 to get the angle change of each leaf. About 8.24 degrees.

Array a start point on the curve, for 18 total points, which will be the base of each leaf.
...

I'm reminded of ArrayGem and variable pitch helix.

- Brian

A .3dm file would be convenient.
From: Michael Gibson
5 Mar 2020   [#3] In reply to [#1]
Hi Tim, there is another array variant "ScriptArray" here which contains rotation code in it:
http://moi3d.com/forum/index.php?webtag=MOI&msg=5595.18

So those could be merged together, take the rotation code out of ScriptArray and put it into ScaleArray to do rotation instead of scaling.

I'll see about putting that together a little later.

- Michael
From: bemfarmer
5 Mar 2020   [#4]
I would suggest adding the rotation code to the standard MoI command Array Curve.
Somehow select initial angle, and select final angle...

I used Array Curve on an arc, and also on a clothoid curve.

- Brian
From: Michael Gibson
5 Mar 2020   [#5] In reply to [#1]
Hi Tim, try the attached RotateArray script, it's a modification of ScaleArray to do rotation instead.

Make sure to include a point object in the array, it will use the point object as the center point for the rotation:







Hope that helps!

- Michael

Attachments:
RotateArray.zip

Image Attachments:
rotate_array1.jpg  rotate_array2.jpg  rotate_array3.jpg 


From: Whiteman Dynamic (TIM_WHITEMAN)
6 Mar 2020   [#6]
Hi guys,

Thank you so much for kindly taking the time to read and understand my fairly simple request, I do appreciate it.

@Brian
Thank you Brian, I did consider the math equation and attempted it, but I think I may have miscalculated it and got undesired results. I can see the mistake I made now with how you suggested calculating it. You're right and I think that is great solution!

My apologies, I should have included my .3dm file which would make things easier. I'll certainly keep that in mind for future questions.

Thanks again for your solution.

@Michael
Thank you very much for so kindly taking the time to help me and for modifying the existing ScaleArray script (which is great by the way!). I will have a look at the code comparatively and try to understand the differences to enhance my understanding of the scripts structure.

Again, such a great community of MoI enthusiasts and a really enjoyable project to follow. MoI continues to be the most relaxing and effortless (but extremely effective) pieces of software that I have ever used! It certainly fixes a lot of the inaccuracies and difficulties of using Adobe Illustrator. It's interesting how inaccurate Adobe's "smart guides" can be when importing .ai files and seeing them in the MoI environment, but that's for another discussion. ;)

Really grateful for your help! Have a great day!

UPDATE
Having used the script, I found a bit of a limitation with using the two scripts combined. If I understand the script correctly, it takes the recently arrayed objects and applies either the Scale (ScaleArray) or Rotation (RotationArray). Once it has completed the task, it removes the arrayed point objects and the array becomes a finished object (in this case closed curve objects). The problem is that it no longer sees the objects as a recent array, so having applied the initial ScaleArray, I was unable to then follow with the RotateArray. I did try adding the points back to the arrayed objects to have a point of reference for the rotations, but it didn't work, I suspect because the script is no longer seeing the result as a recently arrayed result? I have tried butchering together a combination of the two scripts, which almost worked, the input dialogue had both the scale and rotate options, but it seemed to ignore the rotation values, probably because my .js script was amateurishly put together! :s I am hesitant to attach my two script files here in case I cause confusion as they won't work. If there is a way of combine the two scripts or being able to use one after the other, that would be an awesome solution! I hope I don't sound ungrateful?

Thanks again!
From: corchet
6 Mar 2020   [#7]



array ... 18 points on curves ... and ' orient line/line '
From: corchet
6 Mar 2020   [#8] In reply to [#5]
oh yes .. rotate array ! thanks ;)
From: Whiteman Dynamic (TIM_WHITEMAN)
6 Mar 2020   [#9] In reply to [#8]
@corchet

Haha! That's a great workaround! Thank you for your suggestion, I'll take a look... ;)
From: corchet
6 Mar 2020   [#10] In reply to [#9]














to join the leaves ... draw a third line in the middle ... with array ... 19 points on curve

the drawing of the leaves is made only with ' arc tri points ' easy to modify ( 1 bezier handle each ) ;)

and ' orient line line ' everywhere to finish
From: Michael Gibson
6 Mar 2020   [#11] In reply to [#6]
Hi Tim,

re:
> I did try adding the points back to the arrayed objects to have a point of reference
> for the rotations, but it didn't work, I suspect because the script is no longer seeing
> the result as a recently arrayed result?

If you tried this by deleting the line of code that removes the original points, yeah that won't work because you'll have an ordering of objects like:

Point
Point
Point
Obj
Obj
Obj

while these particular commands are expecting what you would get from an array which is arranged like:

Point
Obj
Point
Obj
Point
Obj

However, instead of keeping the original points it is possible to insert a new point, this can be done by adding in one strategic line of code.

Find the section of RotateArray.js that contains this code:

code:
			if ( Obj.isPointObject )
			{
				// Point objects have a "pt" property that gets the x,y,z point. Get that
				// as the rotation origin.
				OriginPt = Obj.pt;
			}
			else
			{
				// Not a point object, add it to the object list to be rotated.
				ObjectSet.addObject( Obj );
			}


and then add in this line of code indicated with >>>> <<<< (without the actual >>>> <<<< characters):


code:
			if ( Obj.isPointObject )
			{
				// Point objects have a "pt" property that gets the x,y,z point. Get that
				// as the rotation origin.
				OriginPt = Obj.pt;

>>>>				ObjectSet.addObject( Obj );     <<<<
			}
			else
			{
				// Not a point object, add it to the object list to be rotated.
				ObjectSet.addObject( Obj );
			}


With that in place a new point object will be created in the ordering that ScaleArray is expecting and so you should then be able to run the results from RotateArray through ScaleArray additionally.

I'll see about making a more generalized "TransformArray" in the future, it would make it a little easier if I implement a helper for it in the core MoI code.

- Michael
From: Frenchy Pilou (PILOU)
8 Mar 2020   [#12]
All that was in 2D or 3D? (you speak about "morphing between the two" )

There is also maybe the LineWeb (Michael) http://moi3d.com/forum/index.php?webtag=MOI&msg=3666.1
or CMorph (Max Smirnov) http://moi3d.com/forum/index.php?webtag=MOI&msg=6373.1
functions ... who can be help for some cases!


From: Mindset (IGNITER)
26 Feb   [#13] In reply to [#11]
Hello everyone,
I need the script to rotate, as it does, incrementally along the array to some maximum degree... but then also please, dwell (continue rotating by said maximum degree some additional elements, [perhaps by quantitative percentage] , and then decrement the rotational effect back down to none... i.e. leaving the last the element in the array result series to remain in its original orientation.
It would be nice if it could also have "Ease in/Ease out" control similar to that which is currently available under the "Limit to axis" option of the twist command.
I am most stymied, for the time being, by the dwell aspect of this perplexity; that is, how to serially rotate multiple array elements by said maximum degree.
Thanks,
MindSet
From: AlexPolo
26 Feb   [#14]
Hi The Scale Array script does something like this but cant seem to find it in the history of the forum.
Regards
Alex.
From: Michael Gibson
26 Feb   [#15] In reply to [#13]
Hi MindSet, you would need to modify the Update() function in the RotateArray.js script file to do that.

There is a line of code in there that calculates the parameter value from 0 to 1:

code:
var t = i / ( Factories.length - 1 );


You would need to put in some more code after that to modify the parameter with your desired behavior.

Here's an example that will step up the rotation along the first third, hold it for the middle third, and then ramp back down the last third. Put this in place of the current Update function:

code:
function Update( Factories, TotalRotationAngle )
{
	for ( var i = 0; i < Factories.length; ++i )
	{
		var t = i / ( Factories.length - 1 );

		////// Added section here
		{
			function SmoothStep( t )
			{
				// https://en.wikipedia.org/wiki/Smoothstep
				if ( t <= 0 ) return 0;
				if ( t >= 1 ) return 1;
				return t * t * (3 - 2*t);
			}

			function GetParam( t, low, high )
			{
				t = (t - low) / (high - low);
				return SmoothStep(t);
			}
		
			if ( t < 1/3 )
			{
				// Beginning third, ramp up smoothly from 0 to full rotation

				t = GetParam( t, 0, 1/3 );
			}
			else if ( t > 2/3 )
			{
				// Ending third, ramp down smoothly from full rotation to 0

				t = GetParam( t, 1, 2/3 );
			}
			else
			{
				// Middle range, hold at full rotation
				t = 1;
			}
		}
		////// End added section


		// Set the angle on the factory
		Factories[i].setInput( 2, t * TotalRotationAngle );
		
		// Update the factory to make it recalculate the rotated result.
		Factories[i].update();
	}
}