admin 发表于 2024-2-23 22:46:51

[每日一码] POLYLINE和ARC相互转换的ARX

static void AsdkConvertPolylineArc2Arc(void)
{
    ads采用name ename;
    ads采用point pt;
    int retval;
    retval = acedEntSel(L"\nPick a LW polyline:", ename, pt);
    if(retval != RTNORM)
      return;

    AcDbPolyline *pPoly;
    AcDbObjectId id;
    Acad::ErrorStatus es;
    acdbGetObjectId(id, ename);
    es = acdbOpenObject((AcDbObject*&)pPoly, id, AcDb::kForRead);
    if (es != Acad::eOk)
    {
      acutPrintf(L"\nERROR: %s", acadErrorStatusText(es));
      return;
    }

    if (pPoly->isA() != AcDbPolyline::desc())
    {
      acutPrintf(L"\nLW polyline not selected.");
      pPoly->close();
      return;
    }

    for (unsigned int i=0; i<pPoly->numVerts()-1; i++)
    {
      double bulge;
      pPoly->getBulgeAt(i, bulge);
      if (bulge == 0.0)// line segment
            continue;

      AcGePoint2d startPt, endPt, centerPt, testPt;
      pPoly->getPointAt(i, startPt);
      pPoly->getPointAt(i+1, endPt);
      AcGeCircArc2d geArc;

      // easy AcDbPolyline method for creating an AcGeCircArc2d
      pPoly->getArcSegAt(i, geArc);
      double start = acutAngle(
                                    asDblArray(geArc.center()),
                                    asDblArray(startPt)
                              );
      double end = acutAngle(
                              asDblArray(geArc.center()),
                              asDblArray(endPt)
                              );
      AcGePoint3d center = AcGePoint3d(
                                          geArc.center().x,
                                          geArc.center().y,
                                          pPoly->elevation()
                                        );

      // if this polyline does not lie in WCS, get its ECS
      // and tranform the center point back to WCS
      if (pPoly->normal() != AcGeVector3d(0,0,1))
      {
            AcGeMatrix3d mat;
            pPoly->getEcs(mat);
            center = center.transformBy(mat);
      }

      AcDbArc* pArc;
      // Check the direction of the arc. If it's clockwise
      // (opposite the AutoCAD default)
      // reverse the start and end points for the AcDbArc.
      if (geArc.isClockWise())
      {
            pArc = new AcDbArc(
                              center,
                              pPoly->normal(),
                              geArc.radius(),
                              end,
                              start
                              );
      }
      else
      {
            pArc = new AcDbArc(
                              center,
                              pPoly->normal(),
                              geArc.radius(),
                              start,
                              end
                              );
      }

      AcCmColor yellow;
      yellow.setColorIndex(2);
      pArc->setColor(yellow);

      //set entity properties such as layer, linetype, color
      // User defined function to add entity to Model Space
      // ...
      postToModelSpace(pArc);
      pArc->close();
    }
    pPoly->close();
}

static void postToModelSpace(AcDbEntity* pEntity)
{
    AcDbBlockTable *pBlockTable;
    AcDbBlockTableRecord *pSpaceRecord;

    AcDbDatabase *pDb
            = acdbHostApplicationServices()->workingDatabase();

    pDb->getSymbolTable(pBlockTable, AcDb::kForRead);
    pBlockTable->getAt
                  (
                        ACDB采用MODEL采用SPACE,
                        pSpaceRecord,
                        AcDb::kForWrite
                  );
    pSpaceRecord->appendAcDbEntity(pEntity);

    pBlockTable->close();
    pEntity->close();
    pSpaceRecord->close();
}

admin 发表于 2024-2-23 22:47:10

Here is a sample code to perform a similar conversion using the AutoCAD .Net API :
using Autodesk.AutoCAD.Geometry;


Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;

PromptEntityOptions peo
            = new PromptEntityOptions("Select a polyline : ");
peo.SetRejectMessage("Not a polyline");
peo.AddAllowedClass(
    typeof(Autodesk.AutoCAD.DatabaseServices.Polyline), true);

PromptEntityResult per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK)
    return;

ObjectId plineId = per.ObjectId;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
    BlockTableRecord btr = tr.GetObject
   (db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;

    Autodesk.AutoCAD.DatabaseServices.Polyline pline =
                tr.GetObject(
                              plineId,
                              OpenMode.ForRead,
                              false
                            )
                as Autodesk.AutoCAD.DatabaseServices.Polyline;

    if (pline != null)
    {
      int segCount = pline.NumberOfVertices - 1;
      for (int cnt = 0; cnt < segCount; cnt++)
      {
            Point3d vertexPt = pline.GetPoint3dAt(cnt);
            SegmentType type = pline.GetSegmentType(cnt);

            switch (type)
            {
                case SegmentType.Arc:
                {
                  CircularArc2d arc2d = pline.GetArcSegment2dAt(cnt);

                  Interval arc2dInterval = arc2d.GetInterval();
                  double startParam = arc2dInterval.LowerBound;
                  double endParam = arc2dInterval.UpperBound;
                  Point2d sp2d = arc2d.EvaluatePoint(startParam);
                  Point2d ep2d = arc2d.EvaluatePoint(endParam);
                  Point2d cp2d = arc2d.Center;
                  double startAngle =
                     (new Line2d(cp2d, sp2d)).Direction.Angle;
                  double endAngle =
                        (new Line2d(cp2d, ep2d)).Direction.Angle;

                  Point3d cp3d = new Point3d(
                                                cp2d.X,
                                                cp2d.Y,
                                                pline.Elevation
                                              );

                  // if this polyline does not lie in WCS, get its ECS
                  // and tranform the center point back to WCS
                  if (pline.Normal != Vector3d.ZAxis)
                  {
                        Matrix3d ecsMatrix = pline.Ecs;
                        cp3d = cp3d.TransformBy(ecsMatrix);
                  }

                  if (arc2d.IsClockWise)
                  {
                        Arc arc = new Arc(cp3d,
                                          pline.Normal,
                                          arc2d.Radius,
                                          endAngle,
                                          startAngle
                                          );
                        arc.ColorIndex = 2;
                        btr.AppendEntity(arc);
                        tr.AddNewlyCreatedDBObject(arc, true);
                  }
                  else
                  {
                        Arc arc = new Arc(cp3d,
                                          pline.Normal,
                                          arc2d.Radius,
                                          startAngle,
                                          endAngle
                                       );
                        arc.ColorIndex = 2;
                        btr.AppendEntity(arc);
                        tr.AddNewlyCreatedDBObject(arc, true);
                  }
                  break;
                }

                case SegmentType.Line:
                {
                  LineSegment2d line2d
                              = pline.GetLineSegment2dAt(cnt);
                  Interval line2dInterval = line2d.GetInterval();
                  double startParam
                                 = line2dInterval.LowerBound;
                  double endParam
                                 = line2dInterval.UpperBound;
                  Point2d sp2d
                            = line2d.EvaluatePoint(startParam);
                  Point2d ep2d
                            = line2d.EvaluatePoint(endParam);
                  Point3d sp3d
                  = new Point3d(sp2d.X, sp2d.Y, pline.Elevation);

                  Point3d ep3d
                  = new Point3d(ep2d.X, ep2d.Y, pline.Elevation);

                  if (pline.Normal != Vector3d.ZAxis)
                  {
                        Matrix3d ecsMatrix = pline.Ecs;
                        sp3d = sp3d.TransformBy(ecsMatrix);
                        ep3d = ep3d.TransformBy(ecsMatrix);
                  }

                  Line line = new Line(sp3d, ep3d);
                  line.ColorIndex = 2;
                  btr.AppendEntity(line);
                  tr.AddNewlyCreatedDBObject(line, true);
                  break;
                }
            }
      }
    }
    tr.Commit();
}
页: [1]
查看完整版本: [每日一码] POLYLINE和ARC相互转换的ARX