<?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 Unexpected side effect with GetReverseParameterCurve in .NET Forum</title>
    <link>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13197108#M1632</link>
    <description>&lt;P&gt;The Curve2d (as the Curve3d) class has a GetReverseParameterCurve method which returns a newly created Curve2d (or Curve3d) with reversed parameters as expected.&lt;/P&gt;
&lt;P&gt;But this method also unexpectedly reverses the source curve.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="csharp"&gt;var ed = Application.DocumentManager.MdiActiveDocument.Editor;
var line1 = new LineSegment2d(new Point2d(0, 0), new Point2d(2, 1));
ed.WriteMessage($"\nline1.StartPoint = {line1.StartPoint} line1.EndPoint: {line1.EndPoint}");
var line2 = line1.GetReverseParameterCurve();
ed.WriteMessage($"\nReferenceEquals(line1, line2): {ReferenceEquals(line1, line2)}");
ed.WriteMessage($"\nline1.StartPoint = {line1.StartPoint} line1.EndPoint: {line1.EndPoint}");
ed.WriteMessage($"\nline2.StartPoint = {line2.StartPoint} line2.EndPoint: {line2.EndPoint}");&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="general"&gt;line1.StartPoint = (0,0) line1.EndPoint: (2,1)
ReferenceEquals(line1, line2): False
line1.StartPoint = (2,1) line1.EndPoint: (0,0)
line2.StartPoint = (2,1) line2.EndPoint: (0,0)&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Fri, 06 Dec 2024 13:33:28 GMT</pubDate>
    <dc:creator>_gile</dc:creator>
    <dc:date>2024-12-06T13:33:28Z</dc:date>
    <item>
      <title>Unexpected side effect with GetReverseParameterCurve</title>
      <link>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13197108#M1632</link>
      <description>&lt;P&gt;The Curve2d (as the Curve3d) class has a GetReverseParameterCurve method which returns a newly created Curve2d (or Curve3d) with reversed parameters as expected.&lt;/P&gt;
&lt;P&gt;But this method also unexpectedly reverses the source curve.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="csharp"&gt;var ed = Application.DocumentManager.MdiActiveDocument.Editor;
var line1 = new LineSegment2d(new Point2d(0, 0), new Point2d(2, 1));
ed.WriteMessage($"\nline1.StartPoint = {line1.StartPoint} line1.EndPoint: {line1.EndPoint}");
var line2 = line1.GetReverseParameterCurve();
ed.WriteMessage($"\nReferenceEquals(line1, line2): {ReferenceEquals(line1, line2)}");
ed.WriteMessage($"\nline1.StartPoint = {line1.StartPoint} line1.EndPoint: {line1.EndPoint}");
ed.WriteMessage($"\nline2.StartPoint = {line2.StartPoint} line2.EndPoint: {line2.EndPoint}");&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="general"&gt;line1.StartPoint = (0,0) line1.EndPoint: (2,1)
ReferenceEquals(line1, line2): False
line1.StartPoint = (2,1) line1.EndPoint: (0,0)
line2.StartPoint = (2,1) line2.EndPoint: (0,0)&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 06 Dec 2024 13:33:28 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13197108#M1632</guid>
      <dc:creator>_gile</dc:creator>
      <dc:date>2024-12-06T13:33:28Z</dc:date>
    </item>
    <item>
      <title>Re: Unexpected side effect with GetReverseParameterCurve</title>
      <link>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13197386#M1633</link>
      <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/109424"&gt;@_gile&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;&lt;P&gt;The Curve2d (as the Curve3d) class has a GetReverseParameterCurve method which returns a newly created Curve2d (or Curve3d) with reversed parameters as expected.&lt;/P&gt;&lt;P&gt;But this method also unexpectedly reverses the source curve.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/109424"&gt;@_gile&lt;/a&gt;&amp;nbsp;. Glad you brought this up as I was bitten by this same assumption as well.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;GetReverseParameterCurved() doesn't create a modified copy of the instance you call the method on. It modifies and returns the same curve you call the method on, in a new managed wrapper.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I think if you try this, it should confirm that:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="csharp"&gt;Curve3d originaCurve = // assign to a Curve3d
Curve3d reversedCopy = originalCurve.GetReverseParameterCurve();

originalCurve == reversedCopy  // should be true.&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;IOW, the result of GetReverseParameterCurve() is just a different managed wrapper that wraps the &lt;EM&gt;same&lt;/EM&gt; underlying AcGeCurve2d/3d instance which the method was invoked on.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The managed docs for that API are a verbatim copy of the native docs for the underlying AcGeCurve2d/3d::reverseParam() method, and are worded to suggest that the input curve is modified, verses it returning a modified &lt;EM&gt;copy&lt;/EM&gt; of same. I would expect that if the API did return a &lt;EM&gt;copy&lt;/EM&gt; of the input curve, it would make that clear.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;If you have a case where you need both the original curve and a reversed clone of it then you could do something like this:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="csharp"&gt;public static Curve3d GetReversedClone(this Curve3d curve)
{
   return ((Curve3d)curve.Clone()).GetReverseParameterCurve();
}&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;You may have noticed that there's a bug in the TryCreatePolyline() method I posted in the other thread which is directly related to this, because if it fails to create a polyline, it may reverse some of the input curves, which may be used in another way. I'm working that and a few other bugs I've found and hope to have an update on the repo soon.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;You can see the bug in the attached DWG. If you try using the &lt;A href="https://github.com/ActivistInvestor/AcMgdLib/tree/main/AcMgdLib/Overrules/RegionExplodeOverrule" target="_blank" rel="noopener"&gt;RegionExplodeOverrule&lt;/A&gt; on it, it fails.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The other bug is that when the Optimize() method that I posted encounters a closed curve that has lines/arcs at both the start &lt;EM&gt;and the end&lt;/EM&gt; of the sequence, it fails to join them in to a single polyline, which it should do.&lt;/P&gt;</description>
      <pubDate>Fri, 06 Dec 2024 15:55:49 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13197386#M1633</guid>
      <dc:creator>ActivistInvestor</dc:creator>
      <dc:date>2024-12-06T15:55:49Z</dc:date>
    </item>
    <item>
      <title>Re: Unexpected side effect with GetReverseParameterCurve</title>
      <link>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13197422#M1634</link>
      <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/4476837"&gt;@ActivistInvestor&lt;/a&gt;&amp;nbsp; a écrit&amp;nbsp;:&lt;BR /&gt;
&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/109424"&gt;@_gile&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;
&lt;P&gt;The Curve2d (as the Curve3d) class has a GetReverseParameterCurve method which returns a newly created Curve2d (or Curve3d) with reversed parameters as expected.&lt;/P&gt;
&lt;P&gt;But this method also unexpectedly reverses the source curve.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/109424"&gt;@_gile&lt;/a&gt;&amp;nbsp;. GetReverseParameterCurved() doesn't create a modified copy of the instance you call the method on. It returns the same curve you call the method on, in a new managed wrapper.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I think if you try this, it should confirm that:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="csharp"&gt;Curve3d originaCurve = // assign to a Curve3d
Curve3d reversedCopy = originalCurve.GetReverseParameterCurve();

originalCurve == reversedCopy  // should be true.&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;IOW, the result of GetReverseParameterCurve() is just a different managed wrapper that wraps the &lt;EM&gt;same&lt;/EM&gt; underlying AcGeCurve2d/3d instance which the method was invoked on.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The managed docs for that API are a verbatim copy of the native docs for the underlying AcGeCurve2d/3d::reverseParam() method, and are worded to suggest that the input curve is modified, verses it returning a modified &lt;EM&gt;copy&lt;/EM&gt; of same. I would expect that if the API did return a &lt;EM&gt;copy&lt;/EM&gt; of the input curve, it would make that clear.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If you have a case where you need both the original curve and a copy of it then you could do something like this:&lt;/P&gt;
&lt;LI-CODE lang="csharp"&gt;public static Curve3d GetReversedClone(this Curve3d curve)
{
   return ((Curve3d)curve.Clone()).GetReverseParameterCurve();
}&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;I think GetReverseParameterCurve does create a new instance of Curve[23]d, because the following returns False.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="csharp"&gt;ReferenceEquals(originalCurve, reversedCopy)&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The override Curve3d.Equals method (as the == operator) seems to compare curves geometry as it does for Point3d.&lt;/P&gt;
&lt;LI-CODE lang="csharp"&gt;var pt1 = new Point3d(1, 2, 3);
var pt2 = new Point3d(1, 2, 3);
ed.WriteMessage($"\nReferenceEquals(pt1, pt2): {ReferenceEquals(pt1, pt2)}"); // returns false
ed.WriteMessage($"\npt1 == pt2): {pt1 == pt2}"); // returns true&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Anyway, if the method reverses the parameters of the instance the method is called on, it should return void instead of Curve3d (as the TransformBy method does).&lt;/P&gt;</description>
      <pubDate>Fri, 06 Dec 2024 16:11:14 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13197422#M1634</guid>
      <dc:creator>_gile</dc:creator>
      <dc:date>2024-12-06T16:11:14Z</dc:date>
    </item>
    <item>
      <title>Re: Unexpected side effect with GetReverseParameterCurve</title>
      <link>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13197505#M1635</link>
      <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/109424"&gt;@_gile&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;So, why&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;ReferenceEquals(originalCurve, reversedCopy)&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;returns False?&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Anyway, if the method reverses the parameters of the the instance you call the method on, it should return void instead of Curve3d (as the TransformBy method does).&lt;/P&gt;&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;ReferenceEquals() compares managed wrappers, and GetReverseParameterCurve() returns a new managed wrapper for the Curve2d/3d that you called the method on. IOW, two managed wrapper instances can both refer to the same underlying 'wrapped' native object. That is why ReferenceEquals() can return false, while object.Equals() returns true both given the same arguments.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;BLOCKQUOTE&gt;The override Curve3d.Equals method (as the == operator) seems to compare curves geometry as it does for Point3d.&lt;/BLOCKQUOTE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;No, it doesn't do that. Curve3d does not override object.Equals() it uses the override defined by DisposableWrapper(), and it doesn't compare the contents or geometry of two Curve3d instances for equality.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The DisposableWrapper base type overrides the object.Equals() method (and the ==/!= operators) to compare the values of the UnmanagedObject property of the two managed wrappers, to determine if both managed wrappers are wrapping the same underlying native object, which is what defines equality of two DisposableWrappers.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The GetReverseParameterCurve() method attempts to maintain parity with the underlying AcGeCurve2d/3d::reverseParam() method, which returns a reference to the instance the method was invoked on, and yes, that has a lot to do with the confusion about this:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="cpp"&gt;AcGeCurve3d&amp;amp; reverseParam();&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 06 Dec 2024 16:30:30 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13197505#M1635</guid>
      <dc:creator>ActivistInvestor</dc:creator>
      <dc:date>2024-12-06T16:30:30Z</dc:date>
    </item>
    <item>
      <title>Re: Unexpected side effect with GetReverseParameterCurve</title>
      <link>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13197980#M1636</link>
      <description>&lt;P&gt;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/109424"&gt;@_gile&lt;/a&gt;, I was able to resolve the bugs that were causing the failure in TryCreatePolyline() as was posted earlier. Your implementation may have the same issue, so I'm sharing my fix in advance of committing it to the repo. See the comments.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="csharp"&gt;/// &amp;lt;summary&amp;gt;
/// Attempts to create a CompositeCurve3d that can be
/// used to create a Polyline, from an input sequence 
/// of Curve3d elements. If the input sequence cannot
/// be used to create a Polyline, this returns null.
/// If the input sequence can be used to create a
/// Polyline, this method normalizes the input elements
/// to be in traversal order and direction before using
/// them to create the result.
/// 
/// This method returns null if the input sequence is 
/// empty or contains a single element, regardless of 
/// its type.
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="curves"&amp;gt;&amp;lt;/param&amp;gt;
/// &amp;lt;param name="validate"&amp;gt;&amp;lt;/param&amp;gt;
/// &amp;lt;param name="tol"&amp;gt;&amp;lt;/param&amp;gt;
/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
/// &amp;lt;exception cref="ArgumentNullException"&amp;gt;&amp;lt;/exception&amp;gt;
/// &amp;lt;exception cref="InvalidOperationException"&amp;gt;&amp;lt;/exception&amp;gt;

public static CompositeCurve3d TryCreatePolyline(this IEnumerable&amp;lt;Curve3d&amp;gt; curves,
   bool validate = false,
   Tolerance tol = default(Tolerance))
{
   if(curves is null)
      throw new ArgumentNullException(nameof(curves));
   var input = curves as Curve3d[] ?? curves.ToArray();
   if(input.Length &amp;lt; 2)
      return null;
   if(tol.Equals(default(Tolerance)))
      tol = Tolerance.Global;
   int count = input.Length;
   var joined = new bool[count];
   Curve3d current = input[0];
   Curve3d next = input[1];
   if(!current.IsPolySegment())
      return null;

   /// Bug fix: This code failed if the start point of the
   /// first curve is coincident with the end point of the
   /// following curve. The code wasn't checking or reversing
   /// the first curve as it does with all following curves:
   
   if(current.StartPoint.IsEqualTo(next.EndPoint, tol))
      current = current.GetReversedClone();

   if(validate)
      current.AssertIsValid();
   var output = new Curve3d[count];
   output[0] = current;
   joined[0] = true;
   var spInput = input.AsSpan();
   var spOutput = output.AsSpan();
   var spJoined = joined.AsSpan();
   int index = 1;
   while(index &amp;lt; count)
   {
      Point3d endPoint = spOutput[index - 1].EndPoint;
      bool found = false;
      for(int i = 0; i &amp;lt; count; i++)
      {
         if(spJoined[i])
            continue;
         current = spInput[i];
         if(!current.IsPolySegment())
            return null;
         if(validate)
            current.AssertIsValid();
         if(endPoint.IsEqualTo(current.StartPoint, tol))
         {
            spOutput[index] = current;
            spJoined[i] = true;
            found = true;
            break;
         }
         else if(endPoint.IsEqualTo(current.EndPoint, tol))
         {
            // Bug fix: Because this method may return null
            // and the input curves may be used in other ways,
            // clones of curves are reversed and replace the
            // original curve to avoid modifying same:
            spOutput[index] = current.GetReversedClone();
            spJoined[i] = true;
            found = true;
            break;
         }
      }
      if(!found)
      {
         throw new InvalidOperationException($"Disjoint curves (index = {index})");
      }
      index++;
   }
   return new CompositeCurve3d(output);
}

public static Curve3d GetReversedClone(this Curve3d curve)
{
   return ((Curve3d)curve.Clone()).GetReverseParameterCurve();
}

&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 06 Dec 2024 20:52:32 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13197980#M1636</guid>
      <dc:creator>ActivistInvestor</dc:creator>
      <dc:date>2024-12-06T20:52:32Z</dc:date>
    </item>
    <item>
      <title>Re: Unexpected side effect with GetReverseParameterCurve</title>
      <link>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13198140#M1637</link>
      <description>&lt;P&gt;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/4476837"&gt;@ActivistInvestor&lt;/a&gt;&lt;/P&gt;
&lt;P&gt;I noticed that sometimes a segment have to be joined to start of the composite curve, so, here's the way I solved it.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="csharp"&gt;/// &amp;lt;summary&amp;gt;
/// Tries to convert the Curve3d sequence into a CompositeCurve3d.
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="source"&amp;gt;Collection this method applies to.&amp;lt;/param&amp;gt;
/// &amp;lt;param name="compositeCurve"&amp;gt;Output composite curve.&amp;lt;/param&amp;gt;
/// &amp;lt;param name="tolerance"&amp;gt;Tolerance used to compare end points.&amp;lt;/param&amp;gt;
/// &amp;lt;param name="predicate"&amp;gt;Predicate used to filter input curves 3d.&amp;lt;/param&amp;gt;
/// &amp;lt;returns&amp;gt;true, if the composite curve could be created; false otherwise.&amp;lt;/returns&amp;gt;
/// &amp;lt;exception cref="ArgumentNullException"&amp;gt;ArgumentNullException is thrown if &amp;lt;paramref name="source"/&amp;gt; is null.&amp;lt;/exception&amp;gt;
public static bool TryConvertToCompositeCurve(
    this IEnumerable&amp;lt;Curve3d&amp;gt; source,
    out CompositeCurve3d compositeCurve,
    Tolerance tolerance = default,
    Predicate&amp;lt;Curve3d&amp;gt; predicate = null)
{
    Assert.IsNotNull(source, nameof(source));

    var isValid = predicate ?? (_ =&amp;gt; true);

    if (tolerance.Equals(default(Tolerance)))
        tolerance = Tolerance.Global;

    compositeCurve = default;

    var input = source as Curve3d[] ?? source.ToArray();

    if (!isValid(input[0]))
        return false;

    int length = input.Length;
    if (length &amp;lt; 2)
        return false;

    var output = new Curve3d[length];
    var done = new bool[length];

    output[0] = input[0];
    done[0] = true;
    int count = 1;
    var startPoint = output[0].StartPoint;
    var endPoint = output[0].EndPoint;

    while (count &amp;lt; length)
    {
        bool found = false;

        for (int i = 0; i &amp;lt; length; i++)
        {
            if (done[i])
                continue;

            var current = input[i];
            if (!isValid(current))
                return false;

            if (endPoint.IsEqualTo(current.StartPoint, tolerance))
            {
                endPoint = current.EndPoint;
                output[count] = current;
                found = done[i] = true;
                break;
            }
            else if (endPoint.IsEqualTo(current.EndPoint, tolerance))
            {
                endPoint = current.StartPoint;
                output[count] = current.GetReverseParameterCurve();
                found = done[i] = true;
                break;
            }
            else if (startPoint.IsEqualTo(current.EndPoint, tolerance))
            {
                startPoint = current.StartPoint;
                for (int j = count; j &amp;gt; 0; j--)
                    output[j] = output[j - 1];
                output[0] = current;
                found = done[i] = true;
                break;
            }
            else if (startPoint.IsEqualTo(current.StartPoint, tolerance))
            {
                startPoint = current.EndPoint;
                for (int j = count; j &amp;gt; 0; j--)
                    output[j] = output[j - 1];
                output[0] = current.GetReverseParameterCurve();
                found = done[i] = true;
                break;
            }
        }

        if (!found)
            return false;

        count++;
    }
    compositeCurve = new CompositeCurve3d(output);
    return true;
}&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 06 Dec 2024 23:27:56 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13198140#M1637</guid>
      <dc:creator>_gile</dc:creator>
      <dc:date>2024-12-06T23:27:56Z</dc:date>
    </item>
    <item>
      <title>Re: Unexpected side effect with GetReverseParameterCurve</title>
      <link>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13198306#M1638</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/109424"&gt;@_gile&lt;/a&gt;, yes, that's what I described above (a set of curves that starts with lines/arcs and ends with lines/arcs, which should be joined into a single polyline). There are also other special cases, such as when there is only a single line or arc between two segments that are neither, and must be left as-is.&lt;/P&gt;</description>
      <pubDate>Sat, 07 Dec 2024 02:33:49 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13198306#M1638</guid>
      <dc:creator>ActivistInvestor</dc:creator>
      <dc:date>2024-12-07T02:33:49Z</dc:date>
    </item>
    <item>
      <title>Re: Unexpected side effect with GetReverseParameterCurve</title>
      <link>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13198699#M1639</link>
      <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/109424"&gt;@_gile&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;&lt;P&gt;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/4476837"&gt;@ActivistInvestor&lt;/a&gt;&lt;/P&gt;&lt;P&gt;I noticed that sometimes a segment have to be joined to start of the composite curve, so, here's the way I solved it.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/109424"&gt;@_gile&lt;/a&gt;, I looked at your code again, and I'm not sure about something.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Do you have examples of when a segment must be joined to the start of the composite curve?&amp;nbsp; In my last post, I mentioned that sometimes a BoundaryLoop's curves can start with lines/arcs and end with lines/arcs, with a spline or elliptical arc between them.&amp;nbsp; And, in that case, all of the lines/arcs should be joined into a single polyline.&amp;nbsp; But perhaps you are citing a more-general use case where user-selected curves may not form a closed figure.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;For example, given these curves extracted from a BoundaryLoop in the order shown:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;0: LineSegment3d&lt;/P&gt;&lt;P&gt;1: ArcSegment3d&lt;/P&gt;&lt;P&gt;2: NurbsCurve3d&lt;/P&gt;&lt;P&gt;3: LineSegment3d&lt;/P&gt;&lt;P&gt;4: NurbsCurve3d&lt;/P&gt;&lt;P&gt;5: LineSegment3d&lt;/P&gt;&lt;P&gt;6: ArcSegment3d&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The resulting set of Curve3ds that are converted to Curve entities must be:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;0: CompositeCurve3d&amp;nbsp; &amp;nbsp;(input elements 5, 6, 0, &amp;amp; 1, in that order)&lt;/P&gt;&lt;P&gt;1: NurbsCurve3d&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (input element 2)&lt;/P&gt;&lt;P&gt;2: LineSegment3d&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(input element 3)&lt;/P&gt;&lt;P&gt;3: NurbsCurve3d&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(input element 4)&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The LineSegment3d in the result is a special case, where a single line or arc segment that lies between two non-line/arc segments does not get converted to a polyline.&lt;/P&gt;</description>
      <pubDate>Sat, 07 Dec 2024 12:02:39 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13198699#M1639</guid>
      <dc:creator>ActivistInvestor</dc:creator>
      <dc:date>2024-12-07T12:02:39Z</dc:date>
    </item>
    <item>
      <title>Re: Unexpected side effect with GetReverseParameterCurve</title>
      <link>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13198858#M1640</link>
      <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/4476837"&gt;@ActivistInvestor&lt;/a&gt;&amp;nbsp; a écrit&amp;nbsp;:
&lt;P class="1733586093743"&gt;&amp;nbsp;&lt;/P&gt;
Do you have examples of when a segment must be joined to the start of the composite curve?&amp;nbsp; In my last post, I mentioned that sometimes a BoundaryLoop's curves can start with lines/arcs and end with lines/arcs, with a spline or elliptical arc between them.&amp;nbsp; And, in that case, all of the lines/arcs should be joined into a single polyline.&amp;nbsp; But perhaps you are citing a more-general use case where user-selected curves may not form a closed figure.&amp;nbsp;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;What I was talking about is cases where some segment have to be joined at the start to the collection in progress. The code post in reply #5 only checks if the start/end point of the current segment matches with the end point of the collection in progress.&lt;/P&gt;
&lt;HR /&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 07 Dec 2024 15:50:51 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13198858#M1640</guid>
      <dc:creator>_gile</dc:creator>
      <dc:date>2024-12-07T15:50:51Z</dc:date>
    </item>
    <item>
      <title>Re: Unexpected side effect with GetReverseParameterCurve</title>
      <link>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13198933#M1641</link>
      <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/109424"&gt;@_gile&lt;/a&gt;&amp;nbsp;wrote:&lt;HR /&gt;What I was talking about is cases where some segment have to be joined at the start to the collection in progress. The code post in reply #5 only checks if the start/end point of the current segment matches with the end point of the collection in progress.&lt;/BLOCKQUOTE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Hi &lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/109424"&gt;@_gile&lt;/a&gt;&amp;nbsp;.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The code in reply #5 was intended &lt;EM&gt;only&lt;/EM&gt; for use with curves extracted from a BoundaryLoop.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Because it is a '&lt;EM&gt;loop&lt;/EM&gt;', you always end up back where you started (e.g., the last curve added to the result should always be connected to the first curve in the result). For that purpose, I don't see any need for adding curves to the start of the chain, or the additional testing needed to do that.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;If you intended your code to be for other, more general-purpose use cases involving curves that are selected by a user or what have you, then the additional testing may be needed, if the input curves are not ordered in any way, and you can't assume they form a closed, non self-intersecting figure.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;But, because we can make certain assumptions about the curves extracted from a BoundaryLoop (e.g, they &lt;EM&gt;must&lt;/EM&gt; form a closed figure), I would rather avoid that additional overhead when dealing only with BoundaryLoop curves, because I don't think it's needed in those cases.&lt;/P&gt;</description>
      <pubDate>Sat, 07 Dec 2024 17:00:05 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13198933#M1641</guid>
      <dc:creator>ActivistInvestor</dc:creator>
      <dc:date>2024-12-07T17:00:05Z</dc:date>
    </item>
    <item>
      <title>Re: Unexpected side effect with GetReverseParameterCurve</title>
      <link>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13199546#M1642</link>
      <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/4476837"&gt;@ActivistInvestor&lt;/a&gt;&amp;nbsp; a écrit&amp;nbsp;:&lt;BR /&gt;The code in reply #5 was intended &lt;EM&gt;only&lt;/EM&gt; for use with curves extracted from a BoundaryLoop.&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;OK, for my part, I was trying to do something that would work whatever the Curve3d collection.&lt;/P&gt;</description>
      <pubDate>Sun, 08 Dec 2024 07:23:23 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13199546#M1642</guid>
      <dc:creator>_gile</dc:creator>
      <dc:date>2024-12-08T07:23:23Z</dc:date>
    </item>
    <item>
      <title>Re: Unexpected side effect with GetReverseParameterCurve</title>
      <link>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13200048#M1643</link>
      <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/109424"&gt;@_gile&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/4476837"&gt;@ActivistInvestor&lt;/a&gt;&amp;nbsp; a écrit&amp;nbsp;:&lt;BR /&gt;The code in reply #5 was intended &lt;EM&gt;only&lt;/EM&gt; for use with curves extracted from a BoundaryLoop.&lt;/BLOCKQUOTE&gt;&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;OK, for my part, I was trying to do something that would work whatever the Curve3d collection.&lt;/P&gt;&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;That's fine for more general-purposes use cases, but I wanted to optimize the code that deals specifically with BoundaryLoop curves.&amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I also have a more general-purpose boundary recognition solution, but it builds &lt;EM&gt;multiple&lt;/EM&gt; chains of curves concurrently, and uses quad-tree spatial indexing to achieve better performance. It will take any set of Curves and join then into one or more contiguous chains. Then, then it will try to join the chains together, which avoids the need to add elements at the start of a chain, since insertions are expensive.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;In your code, you might consider replacing this:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="csharp"&gt;for (int j = count; j &amp;gt; 0; j--)
   output[j] = output[j - 1];
output[0] = current;&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;With:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="csharp"&gt;// Access array elements through Span&amp;lt;T&amp;gt;
var spanOutput = output.AsSpan();

// Insert new element at position 0
// and shift existing elements up by 1:
spanOutput.Slice(0, count).CopyTo(spanOutput.Slice(1));
spanOutput[0] = current;&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sun, 08 Dec 2024 18:32:59 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/unexpected-side-effect-with-getreverseparametercurve/m-p/13200048#M1643</guid>
      <dc:creator>ActivistInvestor</dc:creator>
      <dc:date>2024-12-08T18:32:59Z</dc:date>
    </item>
  </channel>
</rss>

