Grasshopper

algorithmic modeling for Rhino

Identifying numbers in a list relative to previous numbers in the list

I'm having trouble with a definition I'm working on. I'll do my best to describe it clearly.

I have a list of numbers, and I want to identify items in the list which follow specific rules. I assume I will need to script it, but I'm relatively new to the scripting scene and syntax is still a fairly big issue. So if someone can see a way to do this without scripting that would be cool (I'd like to avoid using hoopsnake for it though). This is the idea:

Let X1 be a number in a list of numbers.

If X1 is negative find the next value that is 180 larger or 360 smaller (whichever comes first) and return it's item index

Else If X1 is positive find the next value that is 180 smaller or 360 larger (whichever comes first) and return it's item index

Once the new value is found, store it as X2 and test the remaining  numbers against  it (the next value based on X2 would be X3, then X4, etc... The naming convention isn't important, it can be whatever).

Repeat until the end of the list is reached. 

So basically I'm just looking for the item indexes of the values of all X's. Any advice would be hugely appreciated. 

-Brian

Views: 1283

Replies to This Discussion

 

70 > -110 > 70 > -110 ??

 

How about attaching examples or your list..

The thing is I'm actually looking just to identify numbers within an existing list, not to perform math to create new numbers.

Here is an example.

So it follows that if you were to keep going, the value of 200 would be the next X value since X3 was positive and 200 is the first following value at least 180 smaller than 460.

 

I have no idea without script..

 

Here is a solution with script..

 

There is some error with List<double>.IndexOf() in grasshopper..

 

So I used List<string> instead..

 

 

----

 

  private void RunScript(List<string> datalist, string X1, double Larger, double Smaller, ref object A)
  {
    //your code here…

    current = double.Parse(X1);
    LN = Larger;
    SN = Smaller;

    int index = datalist.IndexOf(X1); // some error of List<double>.IndexOf.. so I used List<string>
    List<int> indices = new List<int>();

    while (true)
    {
      int result = datalist.FindIndex(index, Check);
      if (result > index)
      {
        indices.Add(result);
        index = result;
        current = double.Parse(datalist[index]);
      }
      else break;
    }

    A = indices;


  }

  //<Custom additional code>

  static double current = 0.0;
  static double LN = 0.0;
  static double SN = 0.0;

  private static bool Check(string temp)
  {
    bool flag = false;
    double item = double.Parse(temp);

    if (current > 0)
    {
      if ((item >= current + LN) || (item <= current - SN))
        flag = true;
    }
    else
    {
      if ((item >= current + SN) || (item <= current - LN))
        flag = true;
    }
    return flag;
  }

  //</Custom additional code>

 

 

Attachments:

Wow this is great. Thank you very much Jissi.

I realize I made one mistake though... Maybe you could help me correct it?

The rule of:     if (current > 0)

is only true for finding the first index. After that the rule is slightly different.

After finding the first index, I'd like the rule to change to:

if (current > (previous value of X))

Is this easy to do? I tried editing it myself but wasn't sure how to store the previous value to compare to.

Let me know if this doesn't make sense and I will try to explain it better.

So the examples I posted above would be slightly different. 

Finding the first value after 275 works the same way, the larger or smaller than 0 rule still applies. BUT all values after that follow the new rule I mentioned in the post above. 


What I drew as X3 (460) would actually now be 300. This is because instead of testing if 95 is positive or negative, we are actually testing if it is smaller or larger than the previous X value (in this case 275).

So since X2 (95) is smaller than X1 (275) we actually now want the next value 180 Larger or 360 smaller. The value of 300 is the first item to meet this criteria.

If X2 had been larger than X1, we would want the next value 180 smaller or 360 larger.



Hopefully that makes sense.

Thanks again,

Brian

 

Here you are.. 

 

----

private void RunScript(List<string> datalist, string X1, double Larger, double Smaller, ref object A)
  {
    //your code here…

    current = double.Parse(X1);
    LN = Larger;
    SN = Smaller;

    int index = datalist.IndexOf(X1); // some error of List<double>.IndexOf.. so I used List<string>
    List<int> indices = new List<int>();

    while (true)
    {
      int result = datalist.FindIndex(index, Check);
      if (result > index)
      {
        indices.Add(result);
        index = result;
        previous = current;
        current = double.Parse(datalist[index]);
      }
      else break;
    }

    A = indices;
  }

  //<Custom additional code>

  static double previous = 0.0;
  static double current = 0.0;
  static double LN = 0.0;
  static double SN = 0.0;

  private static bool Check(string temp)
  {
    bool flag = false;
    double item = double.Parse(temp);

    if (current > previous)
    {
      if ((item >= current + LN) || (item <= current - SN))
        flag = true;
    }
    else
    {
      if ((item >= current + SN) || (item <= current - LN))
        flag = true;
    }
    return flag;
  }

  //</Custom additional code>

Attachments:

Awesome! 

I still notice one issue though... If I delete the number 95, then it outputs the first index as 9, the value of which is 460. 

This is incorrect since without the number 95, there are no values in the list that are 180 smaller than 275 or 360 larger than 275, so it should have returned no index values.

So once the value 275 is chosen, the script should go like this:

To find the only the first index:

  if (first value of X1 > 0)
    {
      if ((item >= current + LN) || (item <= current - SN))
        flag = true;
    }
    else
    {
      if ((item >= current + SN) || (item <= current - LN))
        flag = true;
    }

For all indexes after the first index:

  if (current > previous)
    {
      if ((item >= current + LN) || (item <= current - SN))
        flag = true;
    }
    else
    {
      if ((item >= current + SN) || (item <= current - LN))
        flag = true;
    }

Once again, I really appreciate your help.

-Brian

 

Sorry, Brian..

 

I forgot the initialization..

 

Because they (previous, current) are static variables, they have the previous computation result..

 

If you delete 95 from the list, the default previous is not 0 but 300 which is the last value of previous in first computation..

 

So you need a script for initialization like below..

 

----

 

    //your code here…

    previous = 0.0;
    current = double.Parse(X1);
    LN = Larger;
    SN = Smaller;

 

 

 

Excellent that fixed it.

Thanks Jissi!

So since the variable "previous" starts out as 0, when finding the first index the rule is: if (current[275] > previous [0])...

Is this right? It's exactly what I'm looking for I just want to make sure that's how the script is working.

Thanks again,

-Brian

reply to your question..

 

finding the first index the rule is: if (current[275] > previous [0])...

Is this right?

 

Yes.. Correct..

 

It was the problem of missing the Initialization,

"previous = 0.0" makes the static variable as 0.0 before the main script works..

 

now : if (current[275] > previous [0])...

before :  if (current[275] > previous [300 : the last value of previous computation])...

 

Hey Jissi,

I made a couple modifications to the script but it isn't working properly. If you have a couple minutes to look at it that would be awesome. 

Basically instead of measuring the current value against the last value, now I need it to measure against another variable (which I have called "limit" which starts out as 0, get's assigned to 270 or -270 during the first loop, and then is added to or subtracted from during each successive loop (in increments of 180 or 360).

I apologize for the formatting, I think all the indentations were lost when I pasted the code here.

private void RunScript(List<string> datalist, string X1, ref object A)

{
//your code here…

current = double.Parse(X1);
limit = 0.0;
LN = 360;
SN = 180;

int index = datalist.IndexOf(X1); // some error of List<double>.IndexOf.. so I used List<string>
List<int> indices = new List<int>();

while (true)
{
int result = datalist.FindIndex(index, Check);
if (result > index)
{
indices.Add(result);
index = result;
//limit = current;
current = double.Parse(datalist[index]);
}
else break;
}

A = indices;

Print(limit.ToString());
Print(current.ToString());


}

//<Custom additional code>

static double limit = 0.0;
static double current = 0.0;
static double LN = 360.0;
static double SN = 180.0;

private static bool Check(string temp)
{

bool flag = false;
double item = double.Parse(temp);

if (current > limit)
{
if (limit == 0)
{
limit = 270;
flag = true;
}
if (item >= limit + LN && limit != 0)
{
limit = limit + LN;
flag = true;
}
if (item <= limit - SN && limit != 0)
{
limit = limit - SN;
flag = true;
}
}


else
{
if (limit == 0)
{
limit = -270;
//flag = true;
}
if (item >= +limit && limit != 0)
{
limit = limit + SN;
flag = true;
}
if (item <= limit - LN && limit != 0)
{
limit = limit - LN;
flag = true;
}
}
return flag;
}

I'm sure I've made a mistake somewhere, I'm just not sure where.

Let me know if you have any questions.

Thanks again,

-Brian

 

Delete "flag=true;" below..

 

if (current > limit)
{
    if (limit == 0)
    {
        limit = 270;
         //flag = true;
    }

...

 

 

And test with many lists..

I tested with big number in the list, and it works..

Please attach your list and result which you want..

 

RSS

About

Translate

Search

Photos

  • Add Photos
  • View All

Videos

  • Add Videos
  • View All

© 2024   Created by Scott Davidson.   Powered by

Badges  |  Report an Issue  |  Terms of Service