Question

Here is an album of screenshots and corresponding descriptions which should storyboard the problem I'm about to describe.

Now, let me explain my issue in mathematical terms and in the code (C#):

========================

Given:

  • A circle with center of origin at (0,0) and radius = 0.0364

  • A line segment which is parallel to the top of the circle and separated by a small margin (so that the line segment is not tangent to the circle). Size of margin does not matter. The line segment's length is 40% of the diameter of the circle.

Solve for:

A vertical line segment with its starting point at the starting point of the aforementioned line and its ending point touching the circle's edge.

========================

I am not receiving my desired result using AutoCAD's Object Snap feature. The line segment I am trying to draw renders only diagonally using OSnap modes tangent and perpendicular. (See the following C# examples):

Example 1:

bigCircle.GetObjectSnapPoints(
  ObjectSnapModes.ModePerpendicular, 
  0, 
  tipTopCenterPoint1, 
  hatTopP3Dstart1, 
  fakematrix1, 
  p3dcolright, 
  icol1
)

...renders the new line folding in, becoming diagonal. I don't know what it is snapping to, but it's not what I want.

Example 2: This function...

bigCircle.GetObjectSnapPoints(
  ObjectSnapModes.ModeTangent, 
  0,
  tipTopCenterPoint1,
  hatTopP3Dstart1,
  fakematrix1,
  p3dcolright,
  icol1
);

....renders the new line extending out, becoming diagonal. I believe the line is attaching to the point tangent to the circle, but it's not what I want.

Here is what I want to get; how can I do so?

desired result

Was it helpful?

Solution

Rather than try to program around how you'd perform this as a user, I'd stick to good old math for speed and simplicity. The drop distance you're looking for is referred to as the Sagitta. Here is how it could be implemented in code to make it dynamic:

[CommandMethod("MathIsCool")]
public void Draw_Method()
{
    Database db = HostApplicationServices.WorkingDatabase;
    Editor ed = AcadApplication.DocumentManager.MdiActiveDocument.Editor;

    // Parameters (get from user prompt if desired)
    var startP = new Point3d(0, 0, 0);
    var r = 5.64;
    var lineGap = 0.4;
    var chordLen = r * 0.40;

    try
    {
        using (Transaction acTrans = db.TransactionManager.StartOpenCloseTransaction())
        {
            var bt = (BlockTable)acTrans.GetObject(db.BlockTableId, OpenMode.ForWrite);
            var btr = (BlockTableRecord)acTrans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

            // Create the circle
            var circ = new Circle(startP, Vector3d.ZAxis, r);
            btr.AppendEntity(circ);
            acTrans.AddNewlyCreatedDBObject(circ, true);

            // Create the horizontal line
            var hPt1 = new Point3d(startP.X - (chordLen / 2), startP.Y + (r + lineGap), 0);
            var hPt2 = new Point3d(hPt1.X + chordLen, hPt1.Y, 0);
            var hLine = new Line(hPt1, hPt2);
            btr.AppendEntity(hLine);
            acTrans.AddNewlyCreatedDBObject(hLine, true);

            // Create the vertical line
            // Arc sagitta = Sqrt(r*r-l*l);
            var sag = Math.Sqrt(r * r - (chordLen / 2) * (chordLen / 2));
            var vPt2 = new Point3d(hPt1.X, startP.Y + sag, 0);
            var vLine = new Line(hPt1, vPt2);
            btr.AppendEntity(vLine);
            acTrans.AddNewlyCreatedDBObject(vLine, true);

            acTrans.Commit();
        }
    }
    catch (System.Exception ex)
    {
        Debug.WriteLine(ex.ToString());
        ed.WriteMessage(ex.ToString());
    }
}

You can read more about the Sagitta here: http://www.mathopenref.com/sagitta.html

Edit: Updated the transaction to a StartOpenCloseTransaction based on a 60% increase in performance over 100,000 iterations.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top