ADN Open CIS
Сообщество программистов Autodesk в СНГ

21/04/2014

Периметр штриховки с помощью ObjectARX и .NET API

Примитив штриховки в AutoCAD хранит свою геометрию в своих "циклах". Перебирая циклы штриховки можно вычислить периметр штриховки, получая доступ к геометрии. Также, учитывая, какие циклы являются «внутренними», какие «внешние», нужно вычислить отдельно периметр внешний, и периметр внутренний. Здесь пример кода, который вычисляет периметр с использованием ObjectARX и AutoCAD .Net API. Проверка ошибок минимальна для того, чтобы код был более читабелен.

Код - C++: [Выделить]
  1. // Вычисление периметра штриховки при помощи ObjectARX
  2. static void ADS_HatchTest(void)
  3. {
  4.     ads_name en;
  5.     ads_point pt;
  6.     if( acedEntSel(
  7.                     ACRX_T("\nВыберите штриховку :"),
  8.                     en,
  9.                     pt
  10.                    ) != RTNORM )
  11.     {
  12.         return;
  13.     }
  14.  
  15.     AcDbObjectId entId = AcDbObjectId::kNull;
  16.     Acad::ErrorStatus es;
  17.     es = acdbGetObjectId(entId, en);
  18.     if(es != Acad::eOk)
  19.           return;
  20.  
  21.     HatchPerimeter(entId);
  22. }
  23.  
  24. static void HatchPerimeter(AcDbObjectId entId)
  25. {
  26.     Acad::ErrorStatus es;
  27.     AcDbEntity *pEnt;
  28.     es = acdbOpenAcDbEntity(
  29.                             pEnt,
  30.                             entId,
  31.                             AcDb::kForRead
  32.                            );
  33.     if( es != Acad::eOk )
  34.         return;
  35.  
  36.     if( pEnt->isA() != AcDbHatch::desc() )
  37.     {
  38.         acutPrintf(ACRX_T("\nЭто не штриховка. Повторите выбор."));
  39.         pEnt->close();
  40.         return;
  41.     }
  42.  
  43.     AcDbHatch* pHatch = AcDbHatch::cast(pEnt);
  44.  
  45.     int nLoops = pHatch->numLoops(); 
  46.     double totalExternalPerimeter =0.0; 
  47.     double totalInternalPerimeter =0.0;
  48.  
  49.     for(int i=0; i < nLoops; i++)
  50.     {  
  51.         double loopLength = 0.0;
  52.         long loopType;
  53.  
  54.         if( pHatch->loopTypeAt( i )
  55.           & AcDbHatch::kPolyline )
  56.         {    
  57.             AcGePoint2dArray vertices;     
  58.             AcGeDoubleArray bulges;     
  59.             pHatch->getLoopAt(
  60.                                 i,
  61.                                 loopType,
  62.                                 vertices,
  63.                                 bulges
  64.                              );   
  65.             int nVertices = vertices.length();
  66.  
  67.             AcDbPolyline testPoly(nVertices);  
  68.  
  69.             for( int vx=0; vx < nVertices; vx++)
  70.             {
  71.                 double bulge = 0.0;
  72.                 if(bulges.length() < nVertices)
  73.                   bulge = 0.0;
  74.                 else
  75.                   bulge = bulges[vx]; 
  76.                 testPoly.addVertexAt(
  77.                                         vx,
  78.                                         vertices[vx],
  79.                                         bulge
  80.                                     );
  81.             }  
  82.  
  83.             AcGeLineSeg3d ls;
  84.             AcGeCircArc3d as;
  85.             double d = 0.0, p1 = 0.0, p2 = 1.0;
  86.  
  87.             for(int ver = 0; ver < nVertices; ver++)
  88.             {
  89.                 es = testPoly.getBulgeAt( i, d );
  90.                 if( es != Acad::eOk )
  91.                     break;
  92.  
  93.                 if( fabs(d) <= 1e-5 )
  94.                 {
  95.                     es = testPoly.getLineSegAt(ver, ls);
  96.                     if( es != Acad::eOk )
  97.                           break;
  98.                     loopLength += ls.length();
  99.                 }
  100.                 else
  101.                 {
  102.                     AcGePoint2d v1;
  103.                     AcGePoint2d v2;
  104.                     v1.set(
  105.                             vertices[ver].x,
  106.                             vertices[ver].y
  107.                           );
  108.  
  109.                     if (ver == (nVertices - 1))
  110.                     {
  111.                         v2.set(
  112.                                 vertices[0].x,
  113.                                 vertices[0].y
  114.                               );
  115.                     }
  116.                     else
  117.                     {
  118.                         v2.set(
  119.                                  vertices[ver+1].x,
  120.                                  vertices[ver+1].y
  121.                               );
  122.                     }
  123.  
  124.                     if (v1.isEqualTo(v2, AcGeContext::gTol)
  125.                                         == Adesk::kFalse)
  126.                     {
  127.                         es = testPoly.getArcSegAt( i, as );
  128.                         if( es != Acad::eOk )
  129.                             break;
  130.  
  131.                         p1 = as.paramOf(as.startPoint());
  132.                         p2 = as.paramOf(as.endPoint());
  133.  
  134.                         loopLength += as.length( p1, p2 );
  135.                     }
  136.                 }
  137.             }
  138.         }   
  139.         else
  140.         {    
  141.             AcGePoint2dArray vertices;    
  142.             AcGeDoubleArray bulges;
  143.             AcGeVoidPointerArray edgePtrs; 
  144.             AcGeIntArray edgeTypes; 
  145.  
  146.             pHatch->getLoopAt(i, loopType,edgePtrs, edgeTypes ); 
  147.             AcGeCompositeCurve2d compCurve( edgePtrs ); 
  148.  
  149.             AcGeInterval interval;   
  150.             compCurve.getInterval( interval );
  151.  
  152.             loopLength
  153.                 = compCurve.length(
  154.                                     interval.lowerBound(),
  155.                                     interval.upperBound()
  156.                                   );
  157.         }  
  158.  
  159.         if( nLoops > 1 && !(loopType & AcDbHatch::kExternal ))    
  160.             totalInternalPerimeter += loopLength;
  161.         else
  162.             totalExternalPerimeter += loopLength;
  163.     } 
  164.  
  165.     acutPrintf(
  166.                 ACRX_T("\nВнешний периметр : %lf"),
  167.                 totalExternalPerimeter
  168.               );
  169.  
  170.     acutPrintf(
  171.                 ACRX_T("\nВнутренний периметр : %lf"),
  172.                 totalInternalPerimeter
  173.               );
  174.  
  175.     pEnt->close();
  176. }

 

Код - C#: [Выделить]
  1. // Вычисление периметра штриховки при помощи AutoCAD.Net API
  2. [CommandMethod("HatchTest")]
  3. public void HatchTestMethod()
  4. {
  5.     Document activeDoc
  6.             = Application.DocumentManager.MdiActiveDocument;
  7.     Editor ed = activeDoc.Editor;
  8.  
  9.     PromptEntityOptions peo
  10.         = new PromptEntityOptions("Выберите штриховку : ");
  11.  
  12.     peo.SetRejectMessage("\nПожалуйста выберите штриховку ");
  13.     peo.AddAllowedClass(typeof(Hatch), true);
  14.  
  15.     PromptEntityResult per = ed.GetEntity(peo);
  16.     if (per.Status != PromptStatus.OK)
  17.         return;
  18.  
  19.     HatchPerimeter(per.ObjectId);
  20. }
  21.  
  22.  
  23. void HatchPerimeter(ObjectId entId)
  24. {
  25.     Document activeDoc = Application.DocumentManager.MdiActiveDocument;
  26.     Database db = activeDoc.Database;
  27.     Editor ed = activeDoc.Editor;
  28.  
  29.     using (Transaction tr = db.TransactionManager.StartTransaction())
  30.     {
  31.         Hatch hatch = tr.GetObject(entId, OpenMode.ForRead) as Hatch;
  32.         int nLoops = hatch.NumberOfLoops;
  33.  
  34.         double totalExternalPerimeter =0.0;
  35.         double totalInternalPerimeter =0.0;
  36.  
  37.         for(int i=0; i < nLoops; i++)
  38.         {
  39.             double loopLength = 0.0;
  40.             HatchLoopTypes hlt = hatch.LoopTypeAt(i);
  41.             HatchLoop hatchLoop = hatch.GetLoopAt(i);
  42.  
  43.             if ((hatch.LoopTypeAt(i) & HatchLoopTypes.Polyline)
  44.                                     == HatchLoopTypes.Polyline)
  45.             {
  46.                 BulgeVertexCollection bulges
  47.                                             = hatchLoop.Polyline;
  48.  
  49.                 int nVertices = bulges.Count;
  50.                 Polyline testPoly = new Polyline(nVertices);
  51.  
  52.                 for(int vx = 0; vx < bulges.Count; vx++)
  53.                 {
  54.                     BulgeVertex bv = bulges[vx];
  55.                     testPoly.AddVertexAt(
  56.                                             vx,
  57.                                             bv.Vertex,
  58.                                             bv.Bulge,
  59.                                             1.0,
  60.                                             1.0
  61.                                         );
  62.                 }
  63.  
  64.                 LineSegment3d ls = new LineSegment3d();
  65.                 CircularArc3d cs = new CircularArc3d();
  66.                 double d = 0.0, p1 = 0.0, p2 = 1.0;
  67.  
  68.                 for(int ver = 0; ver < nVertices-1; ver++)
  69.                 {
  70.                     d = testPoly.GetBulgeAt(ver);
  71.                     if( Math.Abs(d) <= 1e-5 )
  72.                     {
  73.                         ls = testPoly.GetLineSegmentAt(ver);
  74.                         loopLength += ls.Length;
  75.                     }
  76.                     else
  77.                     {
  78.                         Point2d v1
  79.                             = new Point2d(
  80.                                             bulges[ver].Vertex.X,
  81.                                             bulges[ver].Vertex.Y
  82.                                          );
  83.                         Point2d v2
  84.                             = new Point2d(
  85.                                             bulges[ver + 1].Vertex.X,
  86.                                             bulges[ver + 1].Vertex.Y
  87.                                          );
  88.                         if (v1.IsEqualTo(v2) == false)
  89.                         {
  90.                             cs = testPoly.GetArcSegmentAt(ver);
  91.                             p1 = cs.GetParameterOf(cs.StartPoint);
  92.                             p2 = cs.GetParameterOf(cs.EndPoint);
  93.  
  94.                             loopLength +=
  95.                                 cs.GetLength
  96.                                 (
  97.                                     p1,
  98.                                     p2,
  99.                                     Tolerance.Global.EqualPoint
  100.                                 );
  101.                         }
  102.                     }
  103.                 }
  104.             }
  105.             else
  106.             {
  107.                 Curve2dCollection curves = hatchLoop.Curves;
  108.                 if (curves != null)
  109.                 {
  110.                     foreach (Curve2d curve in curves)
  111.                     {
  112.                         if (hatchLoop.LoopType
  113.                             == HatchLoopTypes.External)
  114.                         {
  115.                             totalExternalPerimeter +=
  116.                                     curve.GetLength(0.0, 1.0);
  117.                         }
  118.                         else
  119.                         {
  120.                             totalInternalPerimeter +=
  121.                                     curve.GetLength(0.0, 1.0);
  122.                         }
  123.                     }
  124.                 }
  125.             }
  126.  
  127.             if (    nLoops > 1 &&
  128.                     ((hlt & HatchLoopTypes.External) != HatchLoopTypes.External))
  129.             {
  130.                 totalInternalPerimeter += loopLength;
  131.             }
  132.             else
  133.             {
  134.                 totalExternalPerimeter += loopLength;
  135.             }
  136.         }
  137.  
  138.         ed.WriteMessage(
  139.                             string.Format
  140.                             (
  141.                                 "\nВнешний периметр : {0}",
  142.                                 totalExternalPerimeter
  143.                             )
  144.                        );
  145.  
  146.         ed.WriteMessage(
  147.                             string.Format
  148.                             (
  149.                                 "\nВнутренний периметр : {0}",
  150.                                 totalInternalPerimeter
  151.                             )
  152.                        );
  153.         tr.Commit();
  154.     }
  155. }

 

Источник: http://adndevblog.typepad.com/autocad/2012/04/perimeter-of-a-hatch-using-objectarx-and-autocad-net-api.html

Обсуждение: http://adn-cis.org/forum/index.php?topic=694

Опубликовано 21.04.2014
Отредактировано 17.03.2016 в 00:46:07