2

I have a problem. I created a TriangleGrid using SkiaSharp. While I was drawing the grid I saved each triangle info in a Dictionary. The Dictionary looks like this:

public class TriangleRegistryObject
{
    public float x1 { get; set; }
    public float y1 { get; set; }
    public float x2 { get; set; }
    public float y2 { get; set; }
    public float x3 { get; set; }
    public float y3 { get; set; }
    public bool Selected { get; set; }
    public bool Visible { get; set; }
}

Now when I select a Triangle I set the boolean Selected to true. At the end I want to check if the Triangles I have selected are connected with eachother. I thought I could count the connected lines. Here is an example image: enter image description here

Now I want to count the purple lines where Selected=true. I have every coordinate (x1, y1) (x2, y2) and (x3, y3).

UPDATE: Here is the code I use that return 0 for me!

public static bool ValidLayout()
{
    bool IsValid;
    int sharedEdges;
    int SelectedTriangles = TriangleRegistry.Count(tr => tr.Value.Selected.Equals(true));
    var triangles = new List<TriangleRegistryList>();

    foreach (KeyValuePair<string, TriangleRegistryObject> row in TriangleRegistry.Where(n => n.Value.Selected == true).ToList())
    {
        triangles.Add(new TriangleRegistryList { x1 = row.Value.x1,
                                                            y1 = row.Value.y1,
                                                            x2 = row.Value.x2,
                                                            y2 = row.Value.y2,
                                                            x3 = row.Value.x3,
                                                            y3 = row.Value.y3
        });
    }

    sharedEdges = triangles.GetKCombs(2).Where(t => t.First().IsAdjacentTo(t.Skip(1).Take(1).Single())).Count();

    if (sharedEdges >= (SelectedTriangles - 1))
    {
        IsValid = true;
    }
    else
    {
        IsValid = false;
    }

    return IsValid;
}

But I have no idea how I can compare the coordinates with each other, to count the connected lines!

Can someone help me?

Community
  • 1
  • 1
A. Vreeswijk
  • 822
  • 1
  • 19
  • 57
  • 1
    [so] is *not* a free code writing service. You are expected to try to **write the code yourself**. After [doing more research](http://meta.stackoverflow.com/questions/261592) if you have a problem you can **post what you've tried** with a **clear explanation of what isn't working** and providing a **[mcve]**. I suggest reading [*How do I ask a Good Question*](/help/how-to-ask) and [*Writing the Perfect Question*](http://codeblog.jonskeet.uk/2010/08/29/writing-the-perfect-question/). Also, be sure to take the [tour]. – Igor May 17 '19 at 15:18
  • I added the code that I got, I have no idea how to continue now! – A. Vreeswijk May 17 '19 at 16:04
  • My first idea would be to compare every triangle in the list with every other triangle, and increment a counter whenever you find 2 triangles that have any 2 vertices in common. There are, more than likely, several more efficient ways to do this. – Bradley Uffner May 17 '19 at 16:08
  • Yeah, I already thought about something like that. But how can I prevent doubles, like knowing which I already compared – A. Vreeswijk May 17 '19 at 16:16
  • @A.Vreeswijk Use the last option in [this](https://stackoverflow.com/a/10629938/526724) answer – Bradley Uffner May 17 '19 at 16:21
  • K-combinations? – A. Vreeswijk May 17 '19 at 16:24
  • yes, that should get you distinct pairs. You may want to modify it to use reference equality, rather than implementing `IComparable`, for simplicity. – Bradley Uffner May 17 '19 at 16:25
  • Here is a Fiddle with a simplified solution. https://dotnetfiddle.net/YK2uP7 – Bradley Uffner May 17 '19 at 16:41
  • Would you consider [this](https://i.imgur.com/FcE2KEE.png) as connected? – John Alexiou May 20 '19 at 17:39
  • No, my triangles are not sorted like that. It is connected if it shares the full line with another triangle. Only the diagonal lines are shared in your image. The horizontal one not – A. Vreeswijk May 20 '19 at 19:16

1 Answers1

2

Here is a very simple solution. It definitely isn't the most efficient, but it gets the job done.

I've added a method to your triangle class that returns true if it shares at least 2 vertices with another triangle.

I've also used a method of finding the distinct permutations that is slightly modified from the one discussed here.

public class Program
{
    public static void Main()
    {
        var triangles = new List<TriangleRegistryObject>{
            new TriangleRegistryObject{x1=10,y1=10, x2=12,y2=10, x3=1,y3=11},
            new TriangleRegistryObject{x1=9,y1=11, x2=11,y2=11, x3=10,y3=10},
            new TriangleRegistryObject{x1=9,y1=11, x2=11,y2=11, x3=10,y3=12},
            new TriangleRegistryObject{x1=34,y1=14, x2=15,y2=11, x3=10,y3=12},
        };

        var sharedEdges = triangles.GetPairs().Where(t => t.first.IsAdjacentTo(t.second)).Count();
        Console.WriteLine($"Number shared edges: {sharedEdges}");
    }
}

public class TriangleRegistryObject
{
    public float x1 { get; set; }
    public float y1 { get; set; }
    public float x2 { get; set; }
    public float y2 { get; set; }
    public float x3 { get; set; }
    public float y3 { get; set; }
    public bool Selected { get; set; }
    public bool Visible { get; set; }

    public IEnumerable<(float x, float y)> GetPoints()
    {
        yield return (x1, y1);
        yield return (x2, y2);
        yield return (x3, y3);
    }

    public bool IsAdjacentTo(TriangleRegistryObject other)
    {
        return this.GetPoints().Intersect(other.GetPoints()).Count() >= 2;
    }
}

public static class EnumerableExtensions
{
    public static IEnumerable<(T first, T second)> GetPairs<T>(this IEnumerable<T> list)
    {
        return list.SelectMany((value, index) => list.Skip(index + 1),
                               (first, second) => (first, second));
    }
}
Bradley Uffner
  • 16,641
  • 3
  • 39
  • 76
  • I have updated the function I use in my question. I added your code to mine and updated my public bool, but it seems that sharedEdges returns 0 when the correct value is supposed to be 2 – A. Vreeswijk May 17 '19 at 17:06
  • Did you try it with the example triangle list in my code to verify that there isn't some other issue? When I run my code locally, I get `2` as the output. The most likely cause of problems is probably coming from the coords being defined as `float`, which may cause some mismatches, depending how you are doing your math. – Bradley Uffner May 17 '19 at 17:08
  • Nevermind, it doesn't return me 0 all the time, but it gives me less then I supposed to have – A. Vreeswijk May 17 '19 at 17:10
  • I'm not entirely sure that counting shared edges will give you the results you want though. For lines, like in your image, it will work with 6 triangles sharing 5 edges, but someone could create a looping shape of 6 triangles sharing 6 edges in a hexagon. – Bradley Uffner May 17 '19 at 17:13
  • I see now that when I click a row of full horizontal row of triangles the value of sharedEdges is always 0. And when I click 2 triangles vertical of each other I get a value of 2 which needs to be 1 – A. Vreeswijk May 17 '19 at 17:14
  • Ahh, i think i see the problem in `IsAdjacentTo`. i'll work on correcting it. – Bradley Uffner May 17 '19 at 17:18
  • I've updated the `TriangleRegistryObject` class in my example. Please give this one a try (added `GetPoints`, and greatly simplified `IsAdjacentTo`). – Bradley Uffner May 17 '19 at 17:23
  • I can easily fix this, but I hope you can with a much pretier code.... Every sharedEdge is doubled. So when I need to get 6 I get 12, etc – A. Vreeswijk May 17 '19 at 17:29
  • Can you give me the coords for some triangle lists that are causing your issue? Rigging up test data on my end isn't easy, and the few combinations I've tested seem to be working correctly. If you could edit your question to include some example coords, it would be VERY helpful. – Bradley Uffner May 17 '19 at 17:31
  • Triangle_1: x1=405, y1=233, x2=675, y2=233, x3=540, y3=467 Triangle_2: x1=270, y1=467, x2=540, y2=467, x3=405, y3=233 Triangle_3: x1=540, y1=467, x2=810, y2=467, x3=675, y3=233 Triangle_4: x1=540, y1=467, x2=810, y2=467, x3=675, y3=701 – A. Vreeswijk May 17 '19 at 17:40
  • I need to get 3 with those 4 triangles, but I get 6 – A. Vreeswijk May 17 '19 at 17:40
  • I have divided it by 2, so for me thats the solution... Thank you so much for your help! – A. Vreeswijk May 17 '19 at 19:35
  • How can I remove doubles? – A. Vreeswijk May 19 '19 at 18:42
  • Sorry, it'll have to wait until Monday, when I'm back in front of a computer. – Bradley Uffner May 19 '19 at 23:48
  • When comparing integers the above would work. but not with floats because of floating point roundoff errors. – John Alexiou May 20 '19 at 15:51
  • If rounding errors become a problem, a custom `IComparer` could be used that allows for some error in precision. – Bradley Uffner May 20 '19 at 16:22
  • @A.Vreeswijk I've updated the example to not contain duplicates from the data you provided. The previous duplicates were coming from a flaw in the way I was checking to unique permutations. – Bradley Uffner May 20 '19 at 17:12