Search code examples
c#.netautocadcadautocad-plugin

Editing arc Normal Z within LW polyline in AutoCAD without exploding polyline


This support article outlines the rough source of my issue: https://www.autodesk.com/support/technical/article/caas/sfdcarticles/sfdcarticles/SOLPROF-flips-Normal-Z-value-of-curved-subtracted-geometry-in-AutoCAD.html

I have arcs in DWG files that have been exported from Rhino where the Normal Z value is "-1" making them face backwards on the plane. The problem is, these arcs are "invisible" as they're hidden inside lightweight polylines. The only time the issue presents itself is when you try to join a polyline with -1 Normal Z with another polyline, in which case the new entity is a spline since the -1 Normal Z arc is technically not 2D so they will not join into a lightwight polyline.

In the C# API I can see the incorrect values by iterating over vertices in polylines and using the GetArcSegmentAt() method. This returns a new CircularArc3d object which shows the incorrect Normal Z value. However, I cannot edit this. Since it's a lightweight polyline (inherently 2D) the only value I can edit for the polyline arc in-place is the bulge value which isn't resetting the Normal Z to the correct value.

I'm attempting something like this:

acPlLwObj = acTrans.GetObject(acObj, OpenMode.ForWrite) as Polyline;
for (int i = 0; i < acPlLwObj.NumberOfVertices; i++)
{
    var acPlArc = acPlLwObj.GetArcSegmentAt(i);
    acPlArc.SetAxes(normalZ2d, acPlArc.ReferenceVector);
}
acTrans.Commit();

...where normalZ2d is a vec3D of: 0, 0, 1.

If I edit the Normal of the Polyline object, it mirrors the polyline on the X axis around the origin to negative.

Is there any way to edit this arc's Normal Z within the lightweight polyline using C# without exploding the polyline and re-creating it? If


Solution

  • I found a workaround. I'm not thrilled with it, but the problem was I was too fixated on the arc entities within the polyline instead of focusing on the polyline itself.

    A polyline vertex has two values that define its location. A Point3d and a Point2d. The Point3d X/Y is normal is relative to the WCS. However, the Point2d normal is relative to the Normal Z of the polyline. If your Normal Z is -1 this will give you two sets of coordinates for each vertex.

    The solution was to "reset" the Point2d coordinates using the X/Y from the Point3d coordinates for each vertex in the offending polylines then invert the bulge value of any arcs. After that I was able to reset the normal on the containing polyline without having any of my vertices rotate around the WCS.

    It hasn't been battle tested but it works on some example drawings I have which are bad:

                        Polyline acPlLwObj;
                        acPlLwObj = acTrans.GetObject(acObj, OpenMode.ForWrite) as Polyline;
                        ed.WriteMessage($"{acPlLwObj.Normal.ToString()}\r\n");
                        for (int i = 0; i < acPlLwObj.NumberOfVertices; i++)
                        {
                            var acPl3DPoint = acPlLwObj.GetPoint3dAt(i);
                            var acPl2DPoint = acPlLwObj.GetPoint2dAt(i);
                            var acPl2DPointNew = new Point2d(acPl3DPoint.X, acPl3DPoint.Y);
                            acPlLwObj.SetPointAt(i, acPl2DPointNew);
                            acPlLwObj.SetBulgeAt(i, -acPlLwObj.GetBulgeAt(i));
                        }
                        acPlLwObj.Normal = normalZ2d;
                        acTrans.Commit();