2

I have convert some C# code to VB.NET to get triangles using LINQ, and both code versions behave the same up to the point where the triangles are selected.

These are my results:

enter image description here

As one can see, a get a list of empty triangles, so I suspect that something is wrong in my Select statement.

Everything else is the same both in VB.NET and C#.

This is my VB.NET code, converted to the best of my knowledge:

    Function GetDelaunayTriangles(ByVal points As IEnumerable(Of Point)) As IEnumerable(Of Triangle)
        Dim result = New List(Of Triangle)()
        Dim rect = Cv2.BoundingRect(points)
        rect.Inflate(10, 10)
        Dim triangles As Vec6f()

        Using subdiv = New Subdiv2D(rect)

            For Each p In points
                Dim cv_p = New OpenCvSharp.Point2f(p.X, p.Y)
                subdiv.Insert(cv_p)
            Next

            triangles = subdiv.GetTriangleList()
        End Using

    Dim nRet As IEnumerable(Of Triangle) = From t In triangles Let p1 = New Point(t(0), t(1)) Let p2 = New Point(t(2), t(3)) Let p3 = New Point(t(4), t(5)) Where rect.Contains(p1) AndAlso rect.Contains(p2) AndAlso rect.Contains(p3) Select New Triangle(p1, p2, p3)

    Return nRet
End Function

And this is the original C# code which works:

    public static IEnumerable<Triangle> GetDelaunayTriangles(IEnumerable<Point> points)
    {
        var result = new List<Triangle>();

        // calculate the bounding box around the points
        var rect = Cv2.BoundingRect(points);
        rect.Inflate(10, 10);

        // the Subdiv2D class handles Delaunay triangulation
        // first we add all points, and then start triangulation
        Vec6f[] triangles;
        using (var subdiv = new Subdiv2D(rect))
        {
            foreach (var p in points)
            {
                var cv_p = new OpenCvSharp.Point2f(p.X, p.Y);
                subdiv.Insert(cv_p);
            }
            triangles = subdiv.GetTriangleList();
        }

        // return result as an enumeration of triangle structs
        return from t in triangles
               let p1 = new Point(t[0], t[1])
               let p2 = new Point(t[2], t[3])
               let p3 = new Point(t[4], t[5])
               where rect.Contains(p1) && rect.Contains(p2) && rect.Contains(p3)
               select new Triangle(p1, p2, p3);
    }

Thank you very much!

Edit:

I have printed the "triangles", and they are exactely the same for both VB.NET and C#. I just don't understand what I'm doing wrong in the Select statement.

Edit:

I have added a screenshot that shows that VS think that "Imports System.Linq" can be removed, which I think is not right.

enter image description here

Edit: Would anybody be so nice and tell me what this LINQ expression would look like in hard code (no more Linq)?

10
  • debug into the linq statement, or do a trace.write from inside Let p1 = ... --> what is the value of t(0) at that time? do you have the proper Imports corresponding to the original usings? Commented Sep 16, 2018 at 21:32
  • when you hover over the p1 in the LINQ statement, does intellisense show a tooltip including the word "range variable" ("bereichsvariable")? I'd be suspecting that it is a scoping issue although a quick attempt to reproduce your scenario worked for me. Commented Sep 16, 2018 at 21:41
  • @dlatikay Can you tell me how to do the trace.write from inside? When I press F8, the debugger steps right through the entire line. Commented Sep 16, 2018 at 21:42
  • 1
    You're returning a lazily evaluated linq query. What happens if you materialize the query? Could you to trying to example the value of a as-yet-unevaluated item? Also, can you provide links to docs or source for the Point and Triangle types? Commented Sep 16, 2018 at 21:48
  • so it is due to lazy evaluation indeed. but how was this different in the C# version? usually when expanding a query result in a VS debugger insight window, it warns you that "this will enumerate the ienumeratble" but if you confirm it can be expected to be complete. this case seems to prove the opposite. Commented Sep 16, 2018 at 22:15

1 Answer 1

4

Your problem is in your Triangle structure. Actually P1 is the same as p1 in VB. So, you should change p1, p2, p3 to eg p1_, p2_, p3_:

Public Sub New(ByVal p1_ As Point, ByVal p2_ As Point, ByVal p3_ As Point)
    P1 = p1_
    P2 = p2_
    P3 = p3_
End Sub
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.