MoI discussion forum
MoI discussion forum

Full Version: Parametric design in MoI?

Show messages:  1-7  …  268-287  288-307  308-327  328-347  348-367  368-387  388-407  …  908-912

From: mkdm
14 May 2016   [#328] In reply to [#326]
Hi Karsten,

Thanks for your reply and your suggestions.

As soon as possible i'll take a better look at those functions and nodes.

Nice day,

Marco.
From: Barry-H
15 May 2016   [#329]
Hi Karsten,
looking at your motor node using the boolean function to indicate a clash of objects gave me an idea.
Is it possible to automatically space an array by using the boolean function.
At the moment I have a AutoArray based on the object bounding box plus gap and orientation
that will automatically fill a given square or rectangle area.
The only problem with this is I have to manually adjust the gap for objects that can
overlap the bounding box.
Ideally I would like to set a minimum gap between objects to maximise the fill.
The way I see it working is to Offset the object by half the gap required.
Space the array centres based on the offset object bounding box .
If boolean of offset object = true ok finish
else reduce centres by given step till boolean true.
So the question is how do I get a true or false from the boolean to use and how to keep
looping reducing the centre distance till true.
Any idea's ?

Cheers
Barry.


Image Attachments:
2016.05.15-11.34.58-[Top].png 


From: Karsten (KMRQUS)
15 May 2016   [#330] In reply to [#329]
Hi Barry,

the simplest way to detect a clash is in my opinion the number of result objects of an intersection. No intersection - no result. So it should be possible to make an interation until no resultobjects exists or vice versa. I don't have time at the moment, so I hope it helps in a first step.

Have a nice day
Karsten
From: Karsten (KMRQUS)
15 May 2016   [#331] In reply to [#330]
p.s.: An iterration algorithm has to be defined inside one node, because I`m not sure if loops are really possible in the nodeeditor.
From: bemfarmer
15 May 2016   [#332] In reply to [#331]
I have seen a feedback loop for another node-type program.
From: mkdm
17 May 2016   [#333] In reply to [#321]
Hi Michael and Max (and everyone),

While i was doing some testing with "Array" family nodes, i wondered a thing regarding the rules followed by Moi and Nodeeditor,
in order to manage the order of selected objects.

I hope that both the .3dm and .nod files that i have attached, are sufficiently clear to explain what i'm trying to understand.

In order to run the example i think that it is necessary the latest Nodeeditor version (0.65).

But, to be clearer, i'll show you what are the steps that i have followed, what is the result that i wanted and what instead is the result that i get.

Given that this is nothing more than an exercise, my goal is to better understand the way used by Moi to manage a set of selected objects,
and if it could be possible to control the order of the objects inside a specific set of selected objects,
and if it could be possible to get the same behavior inside Nodeeditor.

So, i have followed these steps :

01 - Open the .3dm and .nod files
02 - Select all the points in .3dm file, picking them individually in the order shown by the numbers
03 - Assign the selection to the "Selected" node present into the nodeeditor, via the "update" command by right-clicking the node
04 - Run the editor

And....as you can see in the 01_Capture.PNG file, the resulting curve, displayed in violet, doesn't follows the order of picked points.

My question is.....am i doing something wrong ?

Is there a way to instruct Moi or NodeEditor to keep unaltered the order of picked objects ?
Or does Moi apply a different rules to the selected objects, in order to manage a different ordering ?

And, a final consideration...

I think that having the ability to control the order of selected objects, manually or via some sort of programmatic criteria,
would be a very powerful thing inside both Moi and Nodeeditor.

Well then everyone... have a good day,

Marco (mkdm).

Attachments:
03_order_of_selection.3dm
04_order_of_selection.nod

Image Attachments:
01_Capture.PNG  02_Capture.PNG 


From: Karsten (KMRQUS)
17 May 2016   [#334]
Hello to all,

I want to share the idea to make a wrapping function for additional outputs. The advantage would be to reduce nodes. Every node have nearly the same code and new functions could be registered central in one function. The new function would than present in every node that carries the code. The attached code is experimental and full of bugs, but it's the best I can give at the moment. So please study and give a feedback, if it worth to think about.





It's not useful to play with it or integrate the files - only to study what I'm making wrong or make it perhaps better.
The litegraph.js is needed for a function that Marco posted. Thanks for that(for those who can not leave it;-)

Have a nice day
Karsten

Attachments:
litegraph.js
wrappedFunctions.js

Image Attachments:
addOut.gif 


From: Karsten (KMRQUS)
17 May 2016   [#335] In reply to [#334]
forgot to post!

Attachments:
curves2.js


From: mkdm
18 May 2016   [#336]
Hi everyone!

While waiting for new versions of Max's NodeEditor,
i'm doing some experiments with PatternArray selection :

Here's my current unfinished version of the node PatternSelectArray :

code:
// PatternSelectArray
function PatternSelArray()
{
	this.addInput("In","pointarray");
	this.addInput("Start","number");
	this.addInput("Qt_Max","number");
	this.addInput("Step","number");		
	
	this.addOutput("Out","pointarray");
	this.addOutput("Elems","number");
	this.addOutput("Source","pointarray");
	
	this.properties = { mode:["Pattern + Subset", "Pattern + Subset", "Subset + Pattern"],
		pattern:"+",
		start:0,
		qt_max:-1,
		step:1};
	
}

PatternSelArray.title = "PatternSelArray";
PatternSelArray.desc = "PatternSelArray";

PatternSelArray.prototype.onExecute = function()
{
	//if (this.properties.order[0] == "By Selection") {
		
	var source = this.getInputData(0, new pointArray());
	this.properties.pattern = this.properties.pattern.trim();
	
	var usePattern = false;
	var isMixedPattern = false;
	
	// check the pattern
	if (this.properties.pattern != '') {
		// check if pattern contains valid characters
		usePattern = this.properties.pattern.match('^[+\-0-1]+$');
		
		if (usePattern) {
			// check if pattern contains only include characters (+ or 1)
			usePattern = !this.properties.pattern.match('^[+1]+$');
			
			if (usePattern) {
				// if pattern contains both include and exclude characters, then the pattrn will be used
				// otherwise it means that contains only exclude characters (- or 0), and therefore
				// the output pointarray list will be empty
				isMixedPattern = !this.properties.pattern.match('^[\-0]+$');
			}
		}
	}

	var output = new pointArray(); // init to empty list

	if (usePattern) {
		if (isMixedPattern) {
			var len = source.getLength();
			var cn = 0;
			
			for (i = 0; i < len ; i++) {
				if ( this.properties.pattern[cn] === '1' || this.properties.pattern[cn] === '+') {
							
					var source_elem = source.getElement(i);
					
					output.push(source_elem.pt.x,
						source_elem.pt.y,
						source_elem.pt.z,
						source_elem.AngleX,
						source_elem.AngleY,
						source_elem.AngleZ,
						source_elem.Size);
				}
				cn = (cn < this.properties.pattern.length-1) ? cn+1 : 0;
			}
		}
	} else {
		// elaborate the whole source pointarray
		this.properties.pattern = '';
		output = source;		
	}

	var outLength = output.getLength();
	
	this.properties.start = this.getInputData(1, this.properties.start);
	if (this.properties.start < 0) this.properties.start = 0;
	if (this.properties.start > (outLength - 1)) this.properties.start = (outLength - 1);

	this.properties.qt_max = this.getInputData(2, this.properties.qt_max);
	if ((this.properties.qt_max < 0) || (this.properties.qt_max > outLength)) this.properties.qt_max = outLength;
	
	this.properties.step = this.getInputData(3, this.properties.step);
	if (this.properties.step <= 0) this.properties.step = 1;
	if (this.properties.step > outLength) this.properties.step = outLength;
	
	// generate the final pointarray list
	var outputFinal = new pointArray();
		
	for (i = this.properties.start, cont = 0; i < outLength && cont < this.properties.qt_max; i += this.properties.step, cont++) {
		var source_elem = output.getElement(i);
		
		outputFinal.push(source_elem.pt.x,
			source_elem.pt.y,
			source_elem.pt.z,
			source_elem.AngleX,
			source_elem.AngleY,
			source_elem.AngleZ,
			source_elem.Size);
	}
	
	output = null;
	
	this.setOutputData(0, outputFinal);
	this.setOutputData(1, outputFinal.getLength());
	this.setOutputData(2, source);
	
	this.outputs[1].label = "Elems(" + outputFinal.getLength() + ")";
}

LiteGraph.registerNodeType("Arrays/PatternSelArray", PatternSelArray);


The inputs and outputs are :

1 - In : the source PointArray
2 - pattern : the filter pattern string : 1 or + pick the element, 0 or - skip the element
Example "1001" or "+--+"

3 - Start : the first element index of the resulting array after the pattern filtering
4 - Qt_Max : Max quantity of elements present in the final output array
5 - Step : The step used while iterate over the patterned array

6 - Out : the final array
7 - Elems : the number of elements present in the final array
8 - Source : The initial source PointArray


Actually the node works in this way :

1) The pattern is applied to the source array
2) Start , Qt_Max and Step are used to iterate over the patterned PointArray

Actually the property "mode" is not used, but when activated,
will determine the order of the used logic :
First do Pattern operation and then Iterates
or
First Iterates and then do Pattern operation


Nice evening to all,


Marco.
From: James (JFH)
18 May 2016   [#337] In reply to [#334]
Hi Karsten

Great work!

I am totally onboard with your wrapping function for additional outputs proposal.
However could it be achieved with a two tiered menu as shown?
& removed in a similar method to the removal of additional inputs

This way the info panel is not further crowded with non-dynamic elements.

Just a thought
-James

Image Attachments:
Outputs.gif 


From: Karsten (KMRQUS)
18 May 2016   [#338] In reply to [#337]
Hello James,

I had the same idea also, but I could not get it to run:-( I don't understand the core stuff already. Every time I have a short look in it, I have to google for hours. Nevertheless I am still learning. The other reason why I switched back to a selection of the function in the info panel was, that I don't know a good way for multiple outputs (not implemented, but I think possible this way) So the code is only an experiment to explain the idea, not a real solution. I hope Max will implement such a feature. It would help to extend the nodeeditor with such basic functions in a simple way.

Have a nice day
Karsten
From: James (JFH)
18 May 2016   [#339] In reply to [#338]
Karsten/Max

I also think it would be useful to introduce a radio button associated to inputs as shown.
In the case of array nodes, range inputs could all be activated with cascade menu directly on node
or individually in info panel. It would be immediately apparent in the info panel which field has an
active input and which can be activated/deactivated if need be.

The simple remains simple; & the complex is possible

-James
From: mkdm
19 May 2016   [#340] In reply to [#339]
Hi James,

i agree with you.

It would be very useful having the possibility to use a bunch of classic input controls inside nodes,
like radiobuttons and checkboxes.

In my garbage time i'm testing some javascript code that goes in that direction.

But i think that until Max will not release a new updated version of Nodeeditor, all these idea are only valid as a javascript developing practise...

Nice day,

Marco.
From: mkdm
19 May 2016   [#341]
Hi everyone!

here's the new code of my "PatternSelArray" and "ArrayReplicator".

The attached pictures show a simple example.

If you find bugs and errors, please, let me know...

Nice evening to all,

Marco (mkdm)

code:
// PatternSelectArray
function PatternSelArray()
{	
	this.size = [160,70];
	this.minsize = [160,70];
	
	this.addInput("In","pointarray");
	this.addInput("Start_Idx","number");
	this.addInput("Qt_Max","number");
	this.addInput("Step","number");		
	
	this.addOutput("Out","pointarray");
	this.addOutput("Elems","number");
	this.addOutput("Source","pointarray");
	
	this.properties = { mode:["Pattern + Subset", "Pattern + Subset", "Subset + Pattern"],
		pattern:"",
		start_idx:0,
		qt_max:-1,
		step:1 };
	
}

PatternSelArray.title = "PatternSelArray";
PatternSelArray.desc = "PatternSelArray";

PatternSelArray.prototype.onExecute = function()
{		
	/*
		source = the source array
		start_idx = index of the first element to pick
		numMaxElem = max number of elements that will be present in the resulting array
		step = step amount for the for..loop
	*/
	var getPointArraySection = function(source, start_idx, numMaxElem, step) {

		var result = new pointArray();
		
		if (source) {
			var sourceLength = source.getLength();
			for (i = start_idx, cont = 0; i < sourceLength && cont < numMaxElem; i += step, cont++) {
				var source_elem = source.getElement(i);
				
				result.push(source_elem.pt.x,
					source_elem.pt.y,
					source_elem.pt.z,
					source_elem.AngleX,
					source_elem.AngleY,
					source_elem.AngleZ,
					source_elem.Size);
			}
		}
		return result;
	}

	/*
		source = the source array
		pattern = string that define the selection pattern
			1 or + = pick element
			0 or - = skip element
	*/	
	var applyPatternToPointArray = function(source, pattern)
	{
		function ResultObj(pattern) {
			this.array = new pointArray();
			this.pattern = pattern;
		}

		var usePattern = false;
		var isMixedPattern = false;			
		var result = new ResultObj(pattern);
		
		if (pattern) {
			result.pattern = pattern.trim();
			
			// check the pattern
			if (result.pattern != '') {
				// check if pattern contains valid characters
				usePattern = result.pattern.match('^[+\-0-1]+$');
				
				if (usePattern) {
					// check if pattern contains only include characters (+ or 1)
					usePattern = !result.pattern.match('^[+1]+$');
					
					if (usePattern) {
						// if pattern contains both include and exclude characters, then the pattrn will be used
						// otherwise it means that contains only exclude characters (- or 0), and therefore
						// the output pointarray list will be empty
						isMixedPattern = !result.pattern.match('^[\-0]+$');
					}
				}
			}
		}

		if (usePattern) {
			if (isMixedPattern) {
				var len = source.getLength();
				var patLen = result.pattern.length;
				var cn = 0;
				
				for (i = 0; i < len ; i++) {
					if ( result.pattern[cn] === '1' || result.pattern[cn] === '+') {
								
						var source_elem = source.getElement(i);
						
						result.array.push(source_elem.pt.x,
							source_elem.pt.y,
							source_elem.pt.z,
							source_elem.AngleX,
							source_elem.AngleY,
							source_elem.AngleZ,
							source_elem.Size);
					}
					cn = (cn < (patLen - 1)) ? (cn + 1) : 0;
				}
			}
		} else {
			// elaborate the whole source pointarray
			result.pattern = '';
			result.array = source;		
		}

		return result;
	}

	// Business logic
	var source = this.getInputData(0, new pointArray());
	
	this.properties.start_idx = this.getInputData(1, this.properties.start_idx);
	this.properties.qt_max = this.getInputData(2, this.properties.qt_max);
	this.properties.step = this.getInputData(3, this.properties.step);

	if (this.properties.step <= 0) this.properties.step = 1;
	
	var patternedArray;
	var outputIntermediate;
	var outIntermLength;
	
	if (this.properties.mode[0] == "Pattern + Subset") {
		patternedArray = applyPatternToPointArray(source, this.properties.pattern);		
		outputIntermediate = patternedArray.array;		
		outIntermLength = outputIntermediate.getLength();
	} else {
		outputIntermediate = source;
		outIntermLength = source.getLength();
	}

	if ((this.properties.start_idx < 0) || (this.properties.start_idx > (outIntermLength - 1))) this.properties.start_idx = 0;
	
	if (this.properties.qt_max < 0) this.properties.qt_max = outIntermLength;
	
	outputIntermediate = getPointArraySection(outputIntermediate,
						this.properties.start_idx,
						this.properties.qt_max,
						this.properties.step);

	if (this.properties.mode[0] == "Subset + Pattern") {
		patternedArray = applyPatternToPointArray(outputIntermediate, this.properties.pattern);
		
		outputIntermediate = patternedArray.array;
		
		outIntermLength = outputIntermediate.getLength();
	}
						
	this.properties.pattern = patternedArray.pattern;
	patternedArray = null;
	
	this.outputs[0].label = "Out (" + outputIntermediate.getLength() + ")";
	this.outputs[1].label = "Elems (" + outputIntermediate.getLength() + ")";
	this.inputs[0].label = "In (" + source.getLength() + ")";
	
	this.setOutputData(0, outputIntermediate);
	this.setOutputData(1, outputIntermediate.getLength());
	this.setOutputData(2, source);
	
}

LiteGraph.registerNodeType("Arrays/PatternSelArray", PatternSelArray);

// ArrayReplicator
function ArrayReplicator()
{
	this.labels = "abcdef";
	this.size = [140,40];
	this.minsize = [140,40];

	this.internal = {a:1, b:1};
	
	this.addInput("In","pointarray");
	
}

ArrayReplicator.title = "Array Replicator";
ArrayReplicator.desc = "Array Replicator";

ArrayReplicator.prototype.onGetOutputs = function()
{
	var list = [];
	for ( var i = 0; i<this.labels.length; i++ )
	{
		var out = this.labels.charAt(i);
		if ( !(out in this.internal)) { list.push([this.labels.charAt(i),"pointarray", {locked:true}]); break; }
	}
	return list;
}

ArrayReplicator.prototype.onOutputAdded = function(out)
{
	this.internal[out.name] = 1;
	for ( var i in this.outputs ) this.outputs[i].locked = true;
	if (i>1) this.outputs[i].locked = false;
}

ArrayReplicator.prototype.onOutputRemoved = function(slot, name)
{
	if ( this.internal[name] ) delete this.internal[name];
	for ( var i in this.outputs ) this.outputs[i].locked = true;
	if ( this.outputs.length > 2 )this.outputs[i].locked = false;
}

ArrayReplicator.prototype.onAdded = function()
{
	for ( var i = 0; i<this.labels.length; i++ ) if ( this.internal[this.labels.charAt(i)] && this.outputs.length == i ) this.addOutput(this.labels.charAt(i), "pointarray");
	this.setDirtyCanvas(true);
}

ArrayReplicator.prototype.onExecute = function()
{
	var source = this.getInputData(0, new pointArray());

	this.inputs[0].label = "In (" + source.getLength() + ")";
	
	for ( var i = 0; i<this.outputs.length; i++)
	{
		this.setOutputData(i, source);
	}	
}

LiteGraph.registerNodeType("Arrays/ArrayReplicator", ArrayReplicator);

Image Attachments:
01_Capture.PNG  02_Capture.PNG 


From: Frenchy Pilou (PILOU)
19 May 2016   [#342]
Cool thing to have all possible nodes in one wink!
From: Max Smirnov (SMIRNOV)
20 May 2016   [#343]
Hi guys!
Sorry, I didn't write a line of code this week. I was so busy at work.
Maybe next week I'll continue developing of this project.

Marco, this ArrayReplicator looks good, but it will be better if we use a multiple output connections. ;)
From: mkdm
20 May 2016   [#344] In reply to [#343]
Hi Max,

> Marco, this ArrayReplicator looks good, but it will be better if we use a multiple output connections. ;)

I totally agree with you!

While waiting your next NodeEditor release, i'm still playing with array nodes, and after "PatternSelArray" and "ArrayReplicator",
i'm thinking to write :
- "ArrayShuffler" : shuffle the elements inside one array
- "ArrayInspector" : it should output to a textarea, the numeric values of all array elements. Useful for debugging purposes.
- "ArrayExporter" : it should output to a file, the numeric values of all array elements.
- "RandomArray" : In should generate random points inside a 3d cube area.

These ideas are nothing more then a funny and simple javascript programming practice for me,
simple ideas that you might find interesting.

Nice night to all,

Marco.
From: Karsten (KMRQUS)
20 May 2016   [#345] In reply to [#343]
Hello Max,

the main thing , you are well . I enjoy the break:-)

Have a nice weekend
Karsten
From: bemfarmer
25 May 2016   [#346]
Here is a lighter color for the Canvas.
Under nodeeditor/core/imgs, save the original grid.png, and replace it with the lighter grid.png.

The colors of the original grid was inverted. This was done with Gimp2, or with Greenfish Icon Editor Pro (GFIE).
The lighter colors were swapped with GFIE. GFIE does not compress the PNG, so PNGGauntlet was used to shrink the PNG file size.

A button to select the grid colors might be nice, as well as an even lighter grid for printing.

- Brian (Grid.png removed as it is no longer used.)



From: bemfarmer
27 May 2016   [#347] In reply to [#346]
I made an even lighter grid, but the cursor is almost invisible. :-(

The few icon/png editors I've tried have been difficult to use as well.

- Brian

Show messages:  1-7  …  268-287  288-307  308-327  328-347  348-367  368-387  388-407  …  908-912