Get value of an interval

Hi,

In RhinoCommon I can create an interval like this:
Interval interval = new Interval(start,end);
and then get value like this:
interval.ParameterAt(t);

What I am searching for is how to create an interval with multiple parameters not just start and end.
In my case interval goes always from 0 to 1, but at some points it has different values:

Is there any existing math library or method you use that could help me to get a value from such interval?

I guess you could see this geometrically as a degree-1 polyline through the points (0.0, 50), (0.6, 10), (0.8,70) and (1.0, 60). Then intersect the polyline at with a plane parallel to the YZ-plane at X=0.41 to find the answer.

Another way is using this iterative process but this is not the most elegant way and would not take into account any interpolation of values.
@DavidRutten Do you have any idea how to solve this? I believe graph mappers has some sort of similar logic what I am searching for?

        var parameters = new List<double>() { 0 , 0.25, 0.5, 1 };
        var values = new List<double>() { 10, 20, 100, 30 };
        double t = 0.49;
        double value = InterpolateWeightedValues(parameters,values,t);

 public static double InterpolateWeightedValues(List<double> parameters, List<double> values, double t) {

        double value = double.NaN;
        t = Math.Min(1, Math.Max(0, t));


        //Iterate until the end of interval is found
        for (int i = 0; i < parameters.Count; i++) {
            if (t <= parameters[i]) {

                if (i == 0) {
                    value = values[0];
                    break;
                } else {

                    //Remap t
                    double tRemapped = MathUtil.RemapNumbers(t, parameters[i - 1], parameters[i], 0, 1);

                    //Create interval and get value
                    Interval interval = new Interval(values[Math.Max(0, i - 1)], values[i]);
                    value = interval.ParameterAt(tRemapped);
                    break;
                }//if 0
            }//if the end of interval
        }//for loop

        return value;
    }

I suppose you could also use Rhino.Geometry.Interval directly, like so:

List<Interval> xs = new List<Interval>
{
  new Interval(0, 0.25),
  new Interval(0.25, 0.5),
  new Interval(0.5, 1.0)
};
List<Interval> ys = new List<Interval>
{
  new Interval(10, 20),
  new Interval(20, 100),
  new Interval(100,30)
};

var t = 0.49;
for (int i = 0; i < xs.Count; ++i)
{
  if (xs[i].IncludesParameter(t))
  {
    double n = xs[i].NormalizedParameterAt(t);
    double y = ys[i].ParameterAt(n);
    RhinoApp.WriteLine($"Value of t={t} is found at {y}");
    break;
  }
}
1 Like

Hi,

I was curious and solved it through Python by creating a class to contain compound intervals:

import rhinoscriptsyntax as rs
import Rhino
import random

class CompoundIntervals(object):
    
    def __init__(self,pairs):
        
        self.compound_intervals = []
        
        for i in range(len(pairs)-1):
            intervals = ( Rhino.Geometry.Interval(pairs[i][0],pairs[i+1][0]) , Rhino.Geometry.Interval(pairs[i][1],pairs[i+1][1]) )
            self.compound_intervals.append(intervals)
            print intervals
        
    def value_at(self,t):
        
        #assuming a normalized input
        if t < 0: return self.compound_intervals[0][1].ParameterAt(0)
        if t > 1: return self.compound_intervals[-1][1].ParameterAt(1)
        
        
        for interval in self.compound_intervals:
            if interval[0].IncludesParameter(t):
                t_norm = interval[0].NormalizedParameterAt(t)
                return interval[1].ParameterAt(t_norm)

pairs= [(0,10) , (0.25,20) , (0.5,100) , (1,30)]

cpi  = CompoundIntervals(pairs)



for i in range(300):
    t = random.random()
    value = cpi.value_at(t)
    rs.AddPoint(t*100,value,0)

It’s doing the same as @menno solution here above wrapped in a python class

Random input:
image

-Willem

4 Likes