明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 2635|回复: 1

从多段线上直接偏移一条线段或是圆弧

[复制链接]
发表于 2010-6-24 23:01:00 | 显示全部楼层 |阅读模式

AcDbObjectId PostToMS(AcDbEntity *pEnt)
{
 AcDbBlockTable *pBlkTbl;
 acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlkTbl,
  AcDb::kForRead);
 AcDbBlockTableRecord *pMS;
 pBlkTbl->getAt(ACDB_MODEL_SPACE,pMS,AcDb::kForWrite);
 pBlkTbl->close();
 AcDbObjectId EntID;
 pMS->appendAcDbEntity(EntID,pEnt);
 pMS->close();
 return EntID;
}

 

static void ROYMyTest_Test3(void)
 {
  // Add your code for command ROYMyTest._Test3 here
  ads_point pt,SidePt;
  ads_name eName;
  if (acedEntSel(_T("\nSelect a polyline:"),eName,pt)!=RTNORM)
   return;
  ads_real dDistance;
  acedInitGet(RSG_NONEG | RSG_NOZERO,_T(""));
  CString strPrompt;
  struct resbuf rb;
  acedGetVar(_T("OFFSETDIST"),&rb);
  strPrompt.Format(_T("\nInput offset distance<%.2f>:"),rb.resval.rreal);
  int state;
  state=acedGetReal(strPrompt,&dDistance);
  switch (state)
  {
  case RTNONE:
   dDistance=rb.resval.rreal;
   break;
  case RTCAN:
   return;
  case RTNORM:
  default:
   break;
  }
  rb.resval.rreal=dDistance;
  acedSetVar(_T("OFFSETDIST"),&rb);

  AcDbObjectId EntID;
  AcDbEntity *pEnt;
  if (acdbGetObjectId(EntID,eName)!=Acad::eOk
   || acedGetPoint(NULL,_T("\nPick up a point on side to offset:"),SidePt)!=RTNORM)
   return;
  if (acdbOpenAcDbEntity(pEnt,EntID,AcDb::kForRead)!=Acad::eOk)
   return;

  AcDbPolyline *pPLine=NULL;
  if (!pEnt->isKindOf(AcDbPolyline::desc()))
  {
   pEnt->close();
   return;
  }
  else
   pPLine=AcDbPolyline::cast(pEnt);
  if (pPLine==NULL)
   return;

  AcGePoint3d ptOnPolyLine;
  if (pPLine->getClosestPointTo(asPnt3d(pt),ptOnPolyLine)!=Acad::eOk)
  {
   pPLine->close();
   return;
  }

  double dParam;
  AcGeLineSeg3d line3d;
  AcGeCircArc3d CirArc3d;
  AcGeLine3d *pOffsetRetLine3d=NULL;
  AcGeCircArc3d *pOffsetRetCirArc3d=NULL;
  AcGePoint3d SidePtClosestPtOnCurve;
  pPLine->getParamAtPoint(ptOnPolyLine,dParam);
  AcGeVoidPointerArray CurvePointers;
  AcGePoint3d PreStartPt,PreEndPt,OffsetedStartPt,OffsetedEndPt;
  AcGePoint3d arcCenterPt;
  AcGeVector3d OffsetPositiveDirection,CurveDirectionAtPt,ProjectVec,SidePtDirection;
  if (pPLine->segType((int)dParam)==AcDbPolyline::kLine)
  {
   pPLine->getLineSegAt((int)dParam,line3d);
   SidePtClosestPtOnCurve=line3d.closestPointTo(asPnt3d(SidePt));
   CurveDirectionAtPt=line3d.direction();
   SidePtDirection=SidePtClosestPtOnCurve-asPnt3d(SidePt);
   OffsetPositiveDirection=CurveDirectionAtPt.crossProduct(AcGeVector3d::kZAxis);
   rojectVec=SidePtDirection.orthoProject(OffsetPositiveDirection.perpVector());
   if (ProjectVec.isCodirectionalTo(OffsetPositiveDirection))
    line3d.getTrimmedOffset(dDistance,AcGeVector3d::kZAxis,CurvePointers);
   else
    line3d.getTrimmedOffset(-1*dDistance,AcGeVector3d::kZAxis,CurvePointers);
   for (int i=0;i<CurvePointers.length();i++)
   {
    pOffsetRetLine3d=(AcGeLine3d*)CurvePointers.at(i);
    if (pOffsetRetLine3d!=NULL)
    {
     pOffsetRetLine3d->hasStartPoint(OffsetedStartPt);
     pOffsetRetLine3d->hasEndPoint(OffsetedEndPt);
     delete pOffsetRetLine3d;
     AcDbLine *pLine;
     pLine=new AcDbLine();
     pLine->setStartPoint(OffsetedStartPt);
     pLine->setEndPoint(OffsetedEndPt);
     ostToMS((AcDbEntity*)pLine);
     pLine->close();
    }
   }
  }
  else if (pPLine->segType((int)dParam)==AcDbPolyline::kArc)
  {
   pPLine->getArcSegAt((int)dParam,CirArc3d);
   SidePtClosestPtOnCurve=CirArc3d.closestPointTo(asPnt3d(SidePt));
   CurveDirectionAtPt=(CirArc3d.center()-SidePtClosestPtOnCurve).crossProduct(
    CirArc3d.normal());
   SidePtDirection=SidePtClosestPtOnCurve-asPnt3d(SidePt);
   OffsetPositiveDirection=CurveDirectionAtPt.crossProduct(AcGeVector3d::kZAxis);
   rojectVec=SidePtDirection.orthoProject(OffsetPositiveDirection.perpVector());
   if (ProjectVec.isCodirectionalTo(OffsetPositiveDirection))
    CirArc3d.getTrimmedOffset(dDistance,AcGeVector3d::kZAxis,CurvePointers);
   else
    CirArc3d.getTrimmedOffset(-1*dDistance,AcGeVector3d::kZAxis,CurvePointers);

   if (CurvePointers.length()==0)
   {
    acutPrintf(_T("\n输入的偏移距离太大!"));
    return;
   }
    
   for (int i=0;i<CurvePointers.length();i++)
   {
    pOffsetRetCirArc3d=(AcGeCircArc3d*)CurvePointers.at(i);
    if (pOffsetRetCirArc3d!=NULL)
    {
     double dRadius;
     dRadius=pOffsetRetCirArc3d->radius();
     pOffsetRetCirArc3d->hasStartPoint(OffsetedStartPt);
     pOffsetRetCirArc3d->hasEndPoint(OffsetedEndPt);
     arcCenterPt=pOffsetRetCirArc3d->center();
     AcGeVector3d normalVec=pOffsetRetCirArc3d->normal();
     delete pOffsetRetCirArc3d;
     AcDbArc *pArc;
     pArc=new AcDbArc();
     pArc->setCenter(arcCenterPt);
     double dStartAngle=(OffsetedStartPt-arcCenterPt).angleOnPlane(
      AcGePlane::kXYPlane);
     double dEndAngle=(OffsetedEndPt-arcCenterPt).angleOnPlane(
      AcGePlane::kXYPlane);
     if (normalVec.isCodirectionalTo(AcGeVector3d::kZAxis))
     {
      pArc->setStartAngle(dStartAngle);
      pArc->setEndAngle(dEndAngle);
     }
     else
     {
      pArc->setStartAngle(dEndAngle);
      pArc->setEndAngle(dStartAngle);
     }
     
     pArc->setRadius(dRadius);
     ostToMS((AcDbEntity*)pArc);
     pArc->close();
    }
   }
  }
  pPLine->close();
 }

 

从多段线上直接偏移一条线段或是圆弧,就是偏移串接好多段线上的某个图元.

程序比较复杂,不知道有没有更好的方法!

难点是根据点选位置确定偏移方向!

 

发表于 2011-8-13 18:45:48 | 显示全部楼层
希望得到简便的方法!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-25 12:27 , Processed in 0.164312 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表