Grasshopper

algorithmic modeling for Rhino

Hi,

I need to compare two lines in a vb component, and check if they are identical.

So I use "If line1 = Line2 Then...". It works if line1 and line2 are exactly identical (ie from A to B), but it does not work if line1 is from A to B and line2 from B to A, which is quite weird because I compare lines and not vectors, so from a geometrical point of view, line1 should be equal to line2, even if start and end points are reversed.

I tried to use line.Equals method, but the problem is the same.

I tried to use the Line.Equality operator, but I can't find the syntax for it.

I would like to avoid comparing start and end points, because I think it would be faster, but I don't know...

Any idea ?

Views: 2539

Replies to This Discussion

If the lines are just overlapping (and when overlapping have the same length) and not crossing each other what you can do is just check if the midpoints of two lines are the same.

Good one. It does also mean that the deformation mentioned doesn't result in self-intersections otherwise you may get false positives. However it would be easy to add a second conditional to check for false positives once you've determined the mid-points are equal. Since this will very rarely happen, it doesn't matter anymore whether this second clause is fast or slow.

--

David Rutten

david@mcneel.com

Poprad, Slovakia

Good idea Vicente ! 

In my case, it will clearly works. I build this array before applying my formfining deformation to lines, so there is no problem with that.

But I have to build the mid-points to compare (M=(line1.From + line2.To)/2 ...), because I think there is no rhinocommon line member to get this with only one command. So at the end, I am not sure it will be faster than comparing .From and .To. I will try anyway.

Thanks

Line.PointAt(0.5)

You only have to do this once for every line, but you're comparing all lines to all other lines, so there's probably a benefit there. 

--

David Rutten

david@mcneel.com

Poprad, Slovakia

You just have to build the midpoints once for every item. So (without the octree speedup) worst case is n+n², while with the 4 comparisons worst case is (4*n)².

And this is if it takes as long to calculate the midpoint as the distance comparison, but it should be faster since its just adding and dividing while the distance comparison is subtracting, squaring, square rooting and comparing to another number.

 

Beware, it's possible I just wrote a bunch of nonsense.

Distance calculation is in fact much more than Sqrt(dx*dx + dy*dy + dz*dz).

If you look at the RhinoCommon source on GitHub, you can find the GetLengthHelper internal static method which is used to compute distances and vector lengths:

 

internal static double GetLengthHelper(double dx, double dy, double dz)
{
  if (!RhinoMath.IsValidDouble(dx) ||
      !RhinoMath.IsValidDouble(dy) ||
      !RhinoMath.IsValidDouble(dz))
    return 0.0;
  double len;
  double fx = Math.Abs(dx);
  double fy = Math.Abs(dy);
  double fz = Math.Abs(dz);
  if (fy >= fx && fy >= fz)
  {
    len = fx; fx = fy; fy = len;
  }
  else if (fz >= fx && fz >= fy)
  {
    len = fx; fx = fz; fz = len;
  }
  const double ON_DBL_MIN = 2.2250738585072014e-308;
  if (fx > ON_DBL_MIN)
  {
    len = 1.0 / fx;
    fy *= len;
    fz *= len;
    len = fx * Math.Sqrt(1.0 + fy * fy + fz * fz);
  }
  else if (fx > 0.0 && RhinoMath.IsValidDouble(fx))
    len = fx;
  else
    len = 0.0;
  return len;
}

If you know that all your values will always be valid numbers and that they will not result in small distances you could write your own Length or Distance function and squeeze a few more milliseconds.

--

David Rutten

david@mcneel.com

Poprad, Slovakia

I tested the midpoint method, building midpoints once, before my 2 levels loops.

For a 50x50 mesh, the calculation time, wich was 12 sec. with the .From and .To comparison method, drops to 1 sec. 

So it really is efficient. I'll try to manipulate Octree later to improve that, but it already is satisfying to me.

Thanks David and Vicente !

That's strange. You mean it dropped to 1 sec total or you gained one sec so it now computes at 11 secs?

I think best case scenario it should take around 1/4 of the time (3 secs) but I really doubt you can gain that much. If you used nested "if else" statements or "andalso" statements in the previous version most of the iterations should stop after the first distance comparison.

It dropped from 12 to 1 sec. So I gained 11 sec, and it is 12 times faster.

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