<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Distinct XYZ in Revit API Forum</title>
    <link>https://forums.autodesk.com/t5/revit-api-forum/distinct-xyz/m-p/7161606#M57634</link>
    <description>&lt;P&gt;Dear Michail,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Thank you for your very valid query.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You are absolutely correct:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The .NET API does not have any built-in mechanism to compare the Revit API XYZ objects.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;However, it is easy to implement, and I have done so several times in different discussion published by The Building Coder.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Here are the first and last mentions so far:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://thebuildingcoder.typepad.com/blog/2009/05/nested-instance-geometry.html" target="_blank"&gt;http://thebuildingcoder.typepad.com/blog/2009/05/nested-instance-geometry.html&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://thebuildingcoder.typepad.com/blog/2017/06/sensors-bim-ai-revitlookup-and-fuzzy-comparison.html#4" target="_blank"&gt;http://thebuildingcoder.typepad.com/blog/2017/06/sensors-bim-ai-revitlookup-and-fuzzy-comparison.html#4&lt;/A&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;While writing this, I note that The Building Coder samples define the class XyzEqualityComparer in three different modules:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="https://github.com/jeremytammik/the_building_coder_samples" target="_blank"&gt;https://github.com/jeremytammik/the_building_coder_samples&lt;/A&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I hope this helps and suits your needs.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Best regards,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Jeremy&lt;/P&gt;</description>
    <pubDate>Mon, 19 Jun 2017 13:49:00 GMT</pubDate>
    <dc:creator>jeremytammik</dc:creator>
    <dc:date>2017-06-19T13:49:00Z</dc:date>
    <item>
      <title>Distinct XYZ</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/distinct-xyz/m-p/7161065#M57633</link>
      <description>&lt;P&gt;Hi&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I have a list of XYZ points (obtained from MEP connectors).&lt;/P&gt;&lt;P&gt;How to clean it of duplicates (e.g. XYZs with same coordinates)?&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I am trying to:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;var distinctElementConnectors = MyMepUtils.GetALLConnectorsFromElements(elements)
                                          .Where(c =&amp;gt; c.IsConnected)
                                          .Distinct(c =&amp;gt; c.Origin)
                                          .ToHashSet();&lt;/PRE&gt;&lt;P&gt;The .Distinct(c =&amp;gt; c.Origin) doesn't work because .Distinct doesn't know how to compare XYZs (or does it?).&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Please help.&lt;/P&gt;</description>
      <pubDate>Mon, 19 Jun 2017 10:06:44 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/distinct-xyz/m-p/7161065#M57633</guid>
      <dc:creator>MGO-Norsyn</dc:creator>
      <dc:date>2017-06-19T10:06:44Z</dc:date>
    </item>
    <item>
      <title>Re: Distinct XYZ</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/distinct-xyz/m-p/7161606#M57634</link>
      <description>&lt;P&gt;Dear Michail,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Thank you for your very valid query.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You are absolutely correct:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The .NET API does not have any built-in mechanism to compare the Revit API XYZ objects.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;However, it is easy to implement, and I have done so several times in different discussion published by The Building Coder.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Here are the first and last mentions so far:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://thebuildingcoder.typepad.com/blog/2009/05/nested-instance-geometry.html" target="_blank"&gt;http://thebuildingcoder.typepad.com/blog/2009/05/nested-instance-geometry.html&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://thebuildingcoder.typepad.com/blog/2017/06/sensors-bim-ai-revitlookup-and-fuzzy-comparison.html#4" target="_blank"&gt;http://thebuildingcoder.typepad.com/blog/2017/06/sensors-bim-ai-revitlookup-and-fuzzy-comparison.html#4&lt;/A&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;While writing this, I note that The Building Coder samples define the class XyzEqualityComparer in three different modules:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="https://github.com/jeremytammik/the_building_coder_samples" target="_blank"&gt;https://github.com/jeremytammik/the_building_coder_samples&lt;/A&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I hope this helps and suits your needs.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Best regards,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Jeremy&lt;/P&gt;</description>
      <pubDate>Mon, 19 Jun 2017 13:49:00 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/distinct-xyz/m-p/7161606#M57634</guid>
      <dc:creator>jeremytammik</dc:creator>
      <dc:date>2017-06-19T13:49:00Z</dc:date>
    </item>
    <item>
      <title>Re: Distinct XYZ</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/distinct-xyz/m-p/7171420#M57635</link>
      <description>&lt;P&gt;Another direction to go, assuming you implemented your own Point3D and Vector3D wrapper classes like &lt;A href="https://forums.autodesk.com/t5/revit-api-forum/xyz-question/m-p/6460982/highlight/true#M17638" target="_blank"&gt;we previously discussed &lt;/A&gt;is to have those classes implement the IEquatable interface. &amp;nbsp;Here's a shell of the Point3D class showing my implementation:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;    public class Point3D : IEquatable&amp;lt;Point3D&amp;gt;
    {
        public Point3D(XYZ revitXyz)
        {
            XYZ = revitXyz;
        }

        public XYZ XYZ { get; }

        public double X =&amp;gt; XYZ.X;
        public double Y =&amp;gt; XYZ.Y;
        public double Z =&amp;gt; XYZ.Z;
        
        public bool Equals(Point3D other)
        {
            if (ReferenceEquals(other, null)) return false;
            if (ReferenceEquals(this, other)) return true;

            return X.IsAlmostEqualTo(other.X) &amp;amp;&amp;amp;
                   Y.IsAlmostEqualTo(other.Y) &amp;amp;&amp;amp;
                   Z.IsAlmostEqualTo(other.Z);
        }&lt;BR /&gt;&lt;BR /&gt;        public override bool Equals(object obj)&lt;BR /&gt;        {&lt;BR /&gt;            if (ReferenceEquals(null, obj)) return false;&lt;BR /&gt;            if (ReferenceEquals(this, obj)) return true;&lt;BR /&gt;            if (obj.GetType() != GetType()) return false;&lt;BR /&gt;&lt;BR /&gt;            return Equals((Point3D) obj);&lt;BR /&gt;        }

        public override int GetHashCode()
        {
            return Tuple.Create(Math.Round(X, 10),
                    Math.Round(Y, 10),
                    Math.Round(Z, 10)).
                GetHashCode();
        }
    }&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Storing Point3D instances in a hashset will give you your distinct set of points.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;var distinctElementConnectors = MyMepUtils.GetALLConnectorsFromElements(elements)
                                          .Where(c =&amp;gt; c.IsConnected)
                                          .Select(c =&amp;gt; c.Origin.ToPoint3D())
                                          .ToHashSet();&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 22 Jun 2017 16:15:14 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/distinct-xyz/m-p/7171420#M57635</guid>
      <dc:creator>BobbyC.Jones</dc:creator>
      <dc:date>2017-06-22T16:15:14Z</dc:date>
    </item>
    <item>
      <title>Re: Distinct XYZ</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/distinct-xyz/m-p/7173056#M57636</link>
      <description>&lt;P&gt;Thank you for your answer. As always, the solution&amp;nbsp;is already implemented somewhere...&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;But more specifically I was thinking of a way to implement a routine to handle this comparison with LINQ.&lt;/P&gt;</description>
      <pubDate>Fri, 23 Jun 2017 08:00:48 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/distinct-xyz/m-p/7173056#M57636</guid>
      <dc:creator>MGO-Norsyn</dc:creator>
      <dc:date>2017-06-23T08:00:48Z</dc:date>
    </item>
    <item>
      <title>Re: Distinct XYZ</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/distinct-xyz/m-p/7173069#M57637</link>
      <description>&lt;P&gt;Thank you for replying.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Regrettably, I haven't had time to look into your wrapper classes, but I notice that you get a collection of distinct points, while I am interested in getting a collection of distinct connectors where distinction is based on if the origins coincide. &lt;span class="lia-unicode-emoji" title=":winking_face:"&gt;😉&lt;/span&gt;&lt;/P&gt;</description>
      <pubDate>Fri, 23 Jun 2017 07:56:45 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/distinct-xyz/m-p/7173069#M57637</guid>
      <dc:creator>MGO-Norsyn</dc:creator>
      <dc:date>2017-06-23T07:56:45Z</dc:date>
    </item>
    <item>
      <title>Re: Distinct XYZ</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/distinct-xyz/m-p/7173210#M57638</link>
      <description>&lt;P&gt;I define a comparer class that does the job:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;A href="https://github.com/jeremytammik/the_building_coder_samples/blob/master/BuildingCoder/BuildingCoder/Util.cs#L1439-L1465" target="_blank"&gt;https://github.com/jeremytammik/the_building_coder_samples/blob/master/BuildingCoder/BuildingCoder/Util.cs#L1439-L1465&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;    /// &amp;lt;summary&amp;gt;
    /// Compare Connector objects based on their location point.
    /// &amp;lt;/summary&amp;gt;
    public class ConnectorXyzComparer : IEqualityComparer&amp;lt;Connector&amp;gt;
    {
      public bool Equals( Connector x, Connector y )
      {
        return null != x
          &amp;amp;&amp;amp; null != y
          &amp;amp;&amp;amp; IsEqual( x.Origin, y.Origin );
      }

      public int GetHashCode( Connector x )
      {
        return HashString( x.Origin ).GetHashCode();
      }
    }

    /// &amp;lt;summary&amp;gt;
    /// Get distinct connectors from a set of MEP elements.
    /// &amp;lt;/summary&amp;gt;
    public static HashSet&amp;lt;Connector&amp;gt; GetDistinctConnectors(
      List&amp;lt;Connector&amp;gt; cons )
    {
      return cons.Distinct( new ConnectorXyzComparer() )&lt;BR /&gt;        .ToHashSet();
    }
&lt;/PRE&gt;
&lt;P&gt;I implemented that in The Building Coder samples release&amp;nbsp;&lt;SPAN&gt;2018.0.134.1:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;A href="https://github.com/jeremytammik/the_building_coder_samples/releases/tag/2018.0.134.1" target="_blank"&gt;https://github.com/jeremytammik/the_building_coder_samples/releases/tag/2018.0.134.1&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Here is the diff to the previous release:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;A href="https://github.com/jeremytammik/the_building_coder_samples/compare/2018.0.134.0...2018.0.134.1" target="_blank"&gt;https://github.com/jeremytammik/the_building_coder_samples/compare/2018.0.134.0...2018.0.134.1&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Cheers,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Jeremy&lt;/P&gt;</description>
      <pubDate>Fri, 23 Jun 2017 09:20:45 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/distinct-xyz/m-p/7173210#M57638</guid>
      <dc:creator>jeremytammik</dc:creator>
      <dc:date>2017-06-23T09:20:45Z</dc:date>
    </item>
    <item>
      <title>Re: Distinct XYZ</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/distinct-xyz/m-p/7318381#M57639</link>
      <description>&lt;P&gt;Edited and summarised for posterity:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://thebuildingcoder.typepad.com/blog/2017/08/birthday-post-on-the-xyz-class.html" target="_blank"&gt;http://thebuildingcoder.typepad.com/blog/2017/08/birthday-post-on-the-xyz-class.html&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Cheers,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Jeremy&lt;/P&gt;</description>
      <pubDate>Tue, 22 Aug 2017 09:52:54 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/distinct-xyz/m-p/7318381#M57639</guid>
      <dc:creator>jeremytammik</dc:creator>
      <dc:date>2017-08-22T09:52:54Z</dc:date>
    </item>
    <item>
      <title>Re: Distinct XYZ</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/distinct-xyz/m-p/7443692#M57640</link>
      <description>&lt;P&gt;this is how i do to sort and distinct list of XYZ:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Debug.Print("All Points");&lt;BR /&gt;i = 0;&lt;BR /&gt;foreach (XYZ xyz in lstxyzPoints) {&lt;BR /&gt;i++;&lt;BR /&gt;Debug.Print(i.ToString() + " - " + xyz.ToString());&lt;BR /&gt;}&lt;BR /&gt;List&amp;lt;XYZ&amp;gt; lstxyzPointsDistinct = GetDistinctPoints(lstxyzPoints);&lt;BR /&gt;Debug.Print("Distinct Points");&lt;BR /&gt;i = 0;&lt;BR /&gt;foreach (XYZ xyz in lstxyzPointsDistinct) {&lt;BR /&gt;i++;&lt;BR /&gt;Debug.Print(i.ToString() + " - " + xyz.ToString());&lt;BR /&gt;}&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;private List&amp;lt;XYZ&amp;gt; GetDistinctPoints(List&amp;lt;XYZ&amp;gt; lstxyz) {&lt;BR /&gt;List&amp;lt;XYZ&amp;gt; lstxyzRound = new List&amp;lt;XYZ&amp;gt;();&lt;BR /&gt;int i = 1, j = 1;&lt;/P&gt;&lt;P&gt;//round the points to 6 decimal places (you may not need this)&lt;BR /&gt;foreach (XYZ xyz in lstxyz) {&lt;BR /&gt;lstxyzRound.Add(new XYZ(Math.Round(xyz.X, 6), Math.Round(xyz.Y, 6), Math.Round(xyz.Z, 6)));&lt;BR /&gt;}&lt;/P&gt;&lt;P&gt;//order by Z,X,Y (depends on your need)&lt;BR /&gt;lstxyzRound = lstxyzRound.OrderBy(p =&amp;gt; p.Y).ToList();&lt;BR /&gt;lstxyzRound = lstxyzRound.OrderBy(p =&amp;gt; p.X).ToList();&lt;BR /&gt;lstxyzRound = lstxyzRound.OrderBy(p =&amp;gt; p.Z).ToList();&lt;/P&gt;&lt;P&gt;//remove points from list if duplicates&lt;BR /&gt;bool blnDuplicate = true;&lt;BR /&gt;while (blnDuplicate) {&lt;BR /&gt;blnDuplicate = false;&lt;BR /&gt;for (i = j; i &amp;lt; lstxyzRound.Count; i++) {&lt;BR /&gt;if (lstxyzRound[i - 1].DistanceTo(lstxyzRound[i]) &amp;lt; 0.0001) {&lt;BR /&gt;blnDuplicate = true;&lt;BR /&gt;j = i;&lt;BR /&gt;break;&lt;BR /&gt;}&lt;BR /&gt;}&lt;BR /&gt;if (blnDuplicate) {&lt;BR /&gt;lstxyzRound.RemoveAt(j);&lt;BR /&gt;}&lt;BR /&gt;}&lt;BR /&gt;return lstxyzRound;&lt;BR /&gt;}&lt;/P&gt;</description>
      <pubDate>Mon, 09 Oct 2017 03:49:21 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/distinct-xyz/m-p/7443692#M57640</guid>
      <dc:creator>Anonymous</dc:creator>
      <dc:date>2017-10-09T03:49:21Z</dc:date>
    </item>
    <item>
      <title>Re: Distinct XYZ</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/distinct-xyz/m-p/8442348#M57641</link>
      <description>&lt;P&gt;While implementing Jeremy's ConnectorXYZComparer, I've discovered that some connector groups can have much larger tolerances than the 1.0e-9 that Jeremy uses, which gives false negatives. For details see my &lt;A href="https://forums.autodesk.com/t5/revit-api-forum/xyz-question/m-p/8442327#M35243" target="_self"&gt;post&lt;/A&gt; in another thred.&lt;/P&gt;</description>
      <pubDate>Mon, 03 Dec 2018 22:16:41 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/distinct-xyz/m-p/8442348#M57641</guid>
      <dc:creator>MGO-Norsyn</dc:creator>
      <dc:date>2018-12-03T22:16:41Z</dc:date>
    </item>
  </channel>
</rss>

