Offset Ellipse

Moustafa KhalilMoustafa Khalil
4 min read

While using the offset function in the Revit API, I noticed that ellipses don't retain their properties after offsetting. Instead, they are converted to another type of segment classified as a Hermite-spline. How can I keep the ellipse properties after offsetting?

From my experience, the best approach is to recreate the ellipse with the offset value. If the curve is unbound, meaning it is a fully closed ellipse, we can create another ellipse with an offset of the original. Simply take the offset value and add it to the original X and Y radius.

double offset = 1;
var newEllipse = Ellipse
    .CreateCurve(
        originalEllipse.Center,
        originalEllipse.RadiusX + offset,
        originalEllipse.RadiusY + offset,
        originalEllipse.XDirection,
        originalEllipse.YDirection,
        0,
        10
    );

For a bound ellipse (a partially drawn ellipse), we need to get the start and end parameters to use them in the new creation method.

double offset = 1;
var newEllipse = Ellipse
      .CreateCurve(
          originalEllipse.Center,
          originalEllipse.RadiusX + offset,
          originalEllipse.RadiusY + offset,
          originalEllipse.XDirection,
          originalEllipse.YDirection,
          originalEllipse.GetEndParameter(0),
          originalEllipse.GetEndParameter(1)
      );

This method works well when you are only dealing with an ellipse. But what if you need to offset a series of connected curves that include different types of curves?

Since an ellipse is a conic section and can be represented by arcs, we can extract arcs from the ellipse by dividing it into segments and representing each segment as an arc. The number of segments you choose will affect the accuracy of the result. More segments will give a smoother representation but require more computational resources. We can also optimize the result afterward. Let's call this approach A.

Another approach, "B," is to use the Tesselate function. Tesselate will return points that approximate the curve, but only if the curve is bound. From these points, we can start drawing arcs. Although this method will give the most accurate result, it will consume more computational resources.

I have conducted some analysis and performance tests on two curves: one is an ellipse, and the other is a Hermite spline, both with a length of 10920.9 mm. I found that converting any curve to arcs using the LOD "Approach A" provides better-optimized output and less performance overhead compared to the other approach. See the results below:

Conversion MethodSourceTime elapsed (milliseconds)Number of Arcs
LOD : 10 segmentsEllipse1610
Hermite Spline4637
Tesselate : 49 pointsEllipse1610
Hermite Spline4937

The question that might raise, why I would need to convert Hermite spline to arcs. one of the reasons is you can not place walls over Hermite-Spline.

I have place the code, in case you are keen to know how i come up to all of the above:

 // Convert Curve to arc Tesselate
        var stopWatch = Stopwatch.StartNew();
        List<Arc> arcs = new();

        var points = originalEllipse.Tessellate();

        double count = points.Count;
        for (int i = 2; i < count; i += 2)
        {
            var start = points[i - 2];
            var middle = points[i - 1];
            var end = points[i];

            var arc = Arc.Create(start, end, middle);
            if (arcs.Any())
            {
                var lastArc = arcs.Last();
                if (lastArc.Center.IsAlmostEqualTo(arc.Center))
                {
                    arcs[arcs.Count - 1] = Arc.Create(
                        lastArc.GetEndPoint(0),
                        end,
                        lastArc.GetEndPoint(1)
                    );
                }
                else
                {
                    arcs.Add(arc);
                }
            }
            else
                arcs.Add(arc);
        }
        stopWatch.Stop();

        var arcLoop = CurveLoop.Create(arcs.Cast<Curve>().ToList());
        Doc.Create.NewDetailCurveArray(UiDoc.ActiveGraphicalView, arcLoop.ToCurveArray());
 // Convert Curve to arc LOD"
        var stopWatch = Stopwatch.StartNew();
        List<Arc> arcs = new();

        double lod = 10; // level  of detail

        double count = lod * 2;
        for (int i = 2; i <= count; i += 2)
        {
            var start = originalEllipse.Evaluate((i - 2) / count, true);
            var middle = originalEllipse.Evaluate((i - 1) / count, true);
            var end = originalEllipse.Evaluate(i / count, true);

            var arc = Arc.Create(start, end, middle);
            if (arcs.Any())
            {
                var lastArc = arcs.Last();
                if (lastArc.Center.IsAlmostEqualTo(arc.Center))
                {
                    arcs[arcs.Count - 1] = Arc.Create(
                        lastArc.GetEndPoint(0),
                        end,
                        lastArc.GetEndPoint(1)
                    );
                }
                else
                {
                    arcs.Add(arc);
                }
            }
            else
                arcs.Add(arc);
        }
        stopWatch.Stop();

        var arcLoop = CurveLoop.Create(arcs.Cast<Curve>().ToList());
        Doc.Create.NewDetailCurveArray(UiDoc.ActiveGraphicalView, arcLoop.ToCurveArray());
0
Subscribe to my newsletter

Read articles from Moustafa Khalil directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Moustafa Khalil
Moustafa Khalil

I'm Moustafa Khalil El-Sayed, an Egyptian native with a passion for architecture and technology. After completing high school in 1999, I embarked on my journey into architecture, earning my Bachelor's degree in Architecture in 2004. My academic pursuits continued, and I later acquired my Master's degree in Architecture from Wings University. However, my thirst for knowledge extended beyond architectural design, leading me to pursue a degree in Computer Science as well. Driven by a desire to innovate, I began self-teaching computer science, which later empowered me to achieve my Associate degree in Computer Science from the University of the People more easily. Armed with dual expertise in architecture and computer science, I've cultivated a unique skill set that blends creativity with technical acumen. My career has taken me across borders, from Egypt to Oman and the UAE, where I've honed my skills as an architect. As a graduate architect and a proficient .NET BIM Solution Developer, I specialize in translating unique visions into tangible realities. My role extends beyond conventional architectural practices; I leverage technology to streamline processes and enhance project outcomes. My journey into programming began with developing script-based Excel tools to augment project management efforts, notably during the Sharm El Sheikh development. Over time, I expanded my programming prowess to address practical challenges encountered in bridging Revit and AutoCAD within my professional sphere. Several of my applications, born from this evolution, have gained recognition, with some even being featured on the Autodesk website. I am committed to pushing boundaries and continually enriching the intersection of architecture and technology, ensuring that my clients benefit from cutting-edge solutions tailored to their needs.