Problem with iteration of Geometry.Split function through list of lines


#1

Hi,

I’ve worked on a script with great enthusiasm the last week, what I want it to do is divide a roof surface by a list of diagonal lines. To do this, I’ve written a function to count the list length and then check for each line whether the line intersects with the surface and then use it to split the surface.
The first resulting surface is added to a list, and the second resulting surface is the new surface to be cut, effectively slicing the surface into strips. However, when the function returns the list it is empty.

The script needs to be used in combination with the file legrichting.rfa, which needs to exist in your project file when you select a face.

You can ignore the majority of the script (it is used to generate the lines), the fun starts in the tree on the far right side. (Also see the screen shot.) I’ve simulated the function in part with node blocks, to test whether my script def GetRowsFromRoof should work. So far I have no reason to believe that it shouldn’t.

Can someone tell me what I’m doing wrong, or whether there’s an easier way to do this? I’d love to use the While node, but I can’t make sense of it. I find it easier to just write it out line by line.
All help appreciated, sincerest gratitude Bram Weinreder.

legrichting


#2

Hi Bram,

This is a strong start. You seem to have a really good understanding of DS. However neither of the generated lines intersects the roof surface. My suggestion is to use planes instead of lines.

2015-04-02_102501

I have a few small comments on your DS code as well:

2015-04-02_103039

So far so good. Keep up the great work! :slight_smile:


#3

Thank you for checking :slight_smile:

I’ll try to implement your changes. Am I right in guessing that each node puts its result in a list (which is the difference between my test node and the designscript), and that I over-flattened and over-indexed most of it?
You seem to be incorrect on one account though. A line does intersect a face if they’re both on the same plane. But I agree that planes are better when the roof is ever-so-slightly slanted. I’ll let you know if the changes are successful or if I need help with some of it.

Thanks again for your help :slight_smile:


#4

hmm not successful on the first try. It is a shame that you can’t debug DesignScript.

A few questions just to double check a few things, but how do you define something as a list, and what’s the best way to add something to a list? Also: what’s the :var[] doing exactly? (I’m guessing defining a variable as an array, key word guessing)


#5

Yes, the ":var[] " option defines your variable as a list/array and that way the DS code understands it can index it. IMHO indexing is the best way to add items to a list in DS so far.( i.e. list[0] = 0, list[1] = 1, etc.)

So far, I’ve not been able to use “List.AddItemToEnd/Start” in a DS code block.


#6

AddItemToEnd should be easy, it just has to count the number of items and then add the item with a key value similar to the list length (0-14 is a length of 15, which is also the key for the next item).
ToStart would be a bit trickier, it has to iterate through the list, then increase the key value of each item, and assign the key value 0 to the item you wish to add. Or that’s my understanding.

Would it help if I changed the command into GetRowsFromRoof(lines, roof, rows) and insert Rows as an empty list, so it can add the row segments to it which is then returned?

What would help a great deal is if someone could show me how to use the test nodes with the While node; so if a line intersects with the roof it should cut it, adding the row segment to a list and the remaining segment being cut again. If this is possible then I can stop using DesignScript and bugfix one step at a time.


#7

Oh dang, forgot one more comment for the above DS script. Define your variables(or at least the empty list) before initiating the imperative section:

2015-04-02_103039

There are a few good examples for the “LoopWhile” node already. Try the forum’s search function. Tho I’m thinking that an iteration through your list of lines should suffice.


#8

Will try and finetune this until I drop :slight_smile:

Is there a difference between declaring something as a list in these ways?
def Function(variable:var[], …)
variable={};
variable[0]=value;

Thanks again for all the feedback! This is an exciting project and (to me) a proper gateway to real programming. I would really like to see myself grow as a C#.net programmer, and this seems like an easy way to play around with the basics.


#9

OK so it seems like I’m doing something right:

Added my script as is below.

I’ve flattened my lines before input, and I need to index my DoesIntersect command since it returns a list. And I need the first value which is either True or False.
Return=r gives me 10, which is exactly the number of lines that intersect with my roof surface. Return=i gives me the number 15, which is the number of lines in the list. So the script is iterated as often as should, and the if-statement is true as often as should. This (to me) is a leap forward.

Although, everything else related to the split command returns nothing. While in a regular codeblock I can split this face with any of the intersecting lines. So it should be possible…

Getting really close here. All I need is a final lead to get to the solution. Any help appreciated :slight_smile:

The whole script:

def GetRowsFromRoof(lines:var[], roof:var[])
{

rows={};
return = [Imperative]
{
r=0;
i=0;
n=List.Count(lines);
while(i<n)
{
if(lines[i].DoesIntersect(roof)[0] == true)
{

dividedRoof = roof.Split(lines[i]);
newRoof = dividedRoof[1];
row = dividedRoof[0];
rows[r]=row;
roof = newRoof;
r=r+1;
}
i=i+1;
}
return=r;
}
};


#10

Could you try changing line:

if(lines[i].DoesIntersect(roof)[0] == true)

to:

if(lines[i].DoesIntersect(roof[0]) == true)

 


#11

I could, but that would index the roof instead of the DoesIntersect result, and the code would stop working.


#12

Bran,

I had another look at your code and I think we can simplify it if we get rid of the while loop and instead iterate through the list of lines. It gets even simpler if you feed the surface as a surface instead of a list:

Capture3

def GetRowsFromRoof(lines:var[], roof)
{
rows={};
r=0;
return = [Imperative]
{
for(line in lines)
{
if(line.DoesIntersect(roof) == true)
{
dividedRoof = roof.Split(line);
rows[r]= dividedRoof[0];
roof = dividedRoof[1];
r=r+1;
}
}
return=rows;
}
};


#13

Awesomness! I’ll give it a shot, this looks a bunch more straightforward. Thanls for your time, effort and input mate :slight_smile: