Тема: Получение контура штриховки

Можно ли получить "узловые" точки штриховки? Дело в том, что я хочу ее обрезать по прямоугольному контуру. Проблем не возникло ни с чем кроме нее родимой. Штриховка не ассоциативная. Следовательно грипсов у нее аж 1. И тот меня не интересует. Может можно как-то добраться до ограничивающих ее контуров?

Re: Получение контура штриховки

Сам не пробавал, но на AcDbHatch
есть функции:

int numLoops() const;
Acad::ErrorStatus
getLoopAt(int loopIndex, Adesk::Int32& loopType, AcGePoint2dArray& vertices,
 AcGeDoubleArray& bulges) const;

Re: Получение контура штриховки

Если это был намек на такой код,

...
AcGePoint2dArray ptArray;        
AcGeDoubleArray bulges;
Adesk::Int32 loopType;
for (int i = 0; i < pHatch->numLoops(); i++)
{
  pHatch->getLoopAt(i,loopType,ptArray, bulges);
...

то могу сразу сказать, что после его выполнения в ptArray ничего нет :(.
Помоему тут не все так просто.

Re: Получение контура штриховки

Николай пишет:

Помоему тут не все так просто.

Действительно не так просто, но и не слишком сложно. Как вариант:

static void GetHatchBoundary(void)
{
  Acad::ErrorStatus es;
  ads_name en;
  ads_point p;
  double epx = 1e-3;
  if (acedGetDist(NULL,"\nЗадайте точность апроксимации <1e-3> : ",&epx) == RTCAN)
    return;
  epx = max(epx,1e-6);
  while (acedEntSel("\nВыберите штриховку (ENTER-завершение): ",en,p) == RTNORM) {
    AcDbObjectId objId;
    if ((es = acdbGetObjectId (objId,en)) != Acad::eOk) {
      acutPrintf("\nacdbGetObjectId (objId,en)=%s",acadErrorStatusText (es));
      return;
    }
    AcDbObjectPointer<AcDbHatch> pHatch(objId,AcDb::kForRead);
    if ((es = pHatch.openStatus ()) != Acad::eOk) {
      acutPrintf("\npHatch.openStatus ()=%s",acadErrorStatusText (es));
      return;
    }
    int nLoop = pHatch->numLoops();
    // acutPrintf("\npHatch->numLoops()=%d",nLoop);
    long loopType;
    for (int i=0; i < nLoop; i++) {
      if (pHatch->loopTypeAt( i ) & AcDbHatch::kPolyline) {
        AcGePoint2dArray  vertices;
        AcGeDoubleArray   bulges;
        if ((es = pHatch->getLoopAt(i,loopType,vertices,bulges)) != Acad::eOk) {
          acutPrintf("\npHatch->getLoopAt(i,lt,vts2d,blgs)=%s",acadErrorStatusText (es));
          return;
        }
        AcDbPolyline *pPoly = new AcDbPolyline(vertices.length());
        pPoly->setDatabaseDefaults (pHatch->database());
        for (int j=0; j < vertices.length(); j++) {
          pPoly->addVertexAt (j,vertices[j],(bulges.length()<vertices.length()) ? 0.0:bulges[j]);
        }
        pPoly->setClosed (!(loopType & AcDbHatch::kNotClosed));
        pPoly->setNormal (pHatch->normal());
        pPoly->setElevation (pHatch->elevation());
        if (postToDatabase (acdbCurDwg()->currentSpaceId(),pPoly)) {
          pPoly->close ();
        } else {
          delete pPoly;
        }
      } else {
         AcGeVoidPointerArray edgePtrs;
         AcGeIntArray edgeTypes;
         pHatch->getLoopAt(i, loopType,edgePtrs, edgeTypes );
         AcGeCompositeCurve2d compCurve(edgePtrs);
         AcGeInterval interval;  compCurve.getInterval( interval );
         AcGePoint2dArray vertices;
         AcGeDoubleArray  parms;
         compCurve.getSamplePoints(interval.lowerBound(),interval.upperBound(),epx,vertices,parms);
         if (vertices.length () > 0) {
           AcDbPolyline *pPoly = new AcDbPolyline(vertices.length());
           pPoly->setDatabaseDefaults (pHatch->database());
           for (int j=0; j < vertices.length(); j++) {
             pPoly->addVertexAt (j,vertices[j],0.0);
           }
           pPoly->setClosed (Adesk::kTrue);
           pPoly->setNormal (pHatch->normal());
           pPoly->setElevation (pHatch->elevation());
           if (postToDatabase (acdbCurDwg()->currentSpaceId(),pPoly)) {
             pPoly->close ();
           } else {
             delete pPoly;
           }
         }
      }
    }
  }
}

Re: Получение контура штриховки

P.S.: В действительности не только для штриховки, ограниченной полилинией можно получить точный а не апроксимированный контур. Можно и для эллипса, и для сплайна и т.д. Если очень нужно - выложу код, но он достаточно громоздкий...

Re: Получение контура штриховки

Спасибо. Все работает как надо. Результат даже лучше чем я ожидал. А точный контур мне не к чему. Я его все равно не рисую.
Еще раз спасибо.

Re: Получение контура штриховки

а на лиспе такое есть?

Re: Получение контура штриховки

Александр Ривилис пишет:

Если очень нужно — выложу код, но он достаточно громоздкий...

Было бы очень неплохо получить от вас этот код, так как тоже интересуюсь этой темой. Если он чересчур громоздок, то можно на мыло...

Re: Получение контура штриховки

Приблизительно так:

static void GetHatchBoundary(void)
{
  Acad::ErrorStatus es;
  ads_name en;
  ads_point p;
  double epx = -1e-3;
  while (acedEntSel(_T("\nВыберите штриховку (ENTER-завершение): "),en,p) == RTNORM) {
    AcDbObjectId objId;
    if ((es = acdbGetObjectId (objId,en)) != Acad::eOk) {
      acutPrintf(_T("\nacdbGetObjectId (objId,en)=%s"),acadErrorStatusText (es));
      return;
    }
    AcDbObjectPointer<AcDbHatch> pHatch(objId,AcDb::kForRead);
    if ((es = pHatch.openStatus ()) != Acad::eOk) {
      acutPrintf(_T("\npHatch.openStatus ()=%s"),acadErrorStatusText (es));
      return;
    }
    int nLoop = pHatch->numLoops();
    long loopType;
    for (int i=0; i < nLoop; i++) {
      if (pHatch->loopTypeAt( i ) & AcDbHatch::kPolyline) {
        AcGePoint2dArray  vertices;
        AcGeDoubleArray   bulges;
        if ((es = pHatch->getLoopAt(i,loopType,vertices,bulges)) != Acad::eOk) {
          acutPrintf(_T("\npHatch->getLoopAt(i,lt,vts2d,blgs)=%s"),acadErrorStatusText (es));
          return;
        }
        AcDbPolyline *pPoly = new AcDbPolyline(vertices.length());
        pPoly->setDatabaseDefaults (pHatch->database());
        for (int j=0; j < vertices.length(); j++) {
          pPoly->addVertexAt (j,vertices[j],(bulges.length()<vertices.length()) ? 0.0:bulges[j]);
        }
        pPoly->setClosed (!(loopType & AcDbHatch::kNotClosed));
        pPoly->setNormal (pHatch->normal());
        pPoly->setElevation (pHatch->elevation());
        if (postToDatabase (acdbCurDwg()->currentSpaceId(),pPoly)) {
          pPoly->close ();
        } else {
          delete pPoly;
        }
      } else {
        AcGeVoidPointerArray edgePtrs;
        AcGeIntArray edgeTypes;
        pHatch->getLoopAt(i, loopType,edgePtrs,edgeTypes);
        for (int j=0; j < edgePtrs.length(); j++) {
          AcDbEntity *pEnt = NULL;
          AcGeCurve3d *gent3d = static_cast<AcGeCurve3d *>(edgePtrs[j]);
          if (gent3d) {
            switch(gent3d->type())
            {
            case AcGe::kLineSeg2d:
              {
                AcGeLineSeg3d *lseg3d = static_cast<AcGeLineSeg3d *>(gent3d);
                if (lseg3d) {
                  AcDbPolyline *pPline = new AcDbPolyline(2);
                  pPline->setDatabaseDefaults (pHatch->database());
                  pPline->addVertexAt(0,asPnt2d(asDblArray(lseg3d->startPoint())));
                  pPline->addVertexAt(0,asPnt2d(asDblArray(lseg3d->endPoint())));
                  pPline->setNormal(pHatch->normal());
                  pPline->setElevation(pHatch->elevation());
                  pEnt = pPline;
                }
              }
              break;
            case AcGe::kCircArc2d:
              {
                AcGeCircArc3d *cArc3d = static_cast<AcGeCircArc3d *>(gent3d);
                if (cArc3d) {
                  AcGePoint3d  center = cArc3d->center();
                  AcGeVector3d normal = cArc3d->normal();
                  AcGeVector3d refVec = cArc3d->refVec();
                  AcGePlane plane = AcGePlane(center, normal);
                  double ang = refVec.angleOnPlane(plane);
                  AcDbArc *pArc = new AcDbArc(center, normal, cArc3d->radius(),cArc3d->startAng()+ang,cArc3d->endAng()+ang);
                  pArc->setDatabaseDefaults(pHatch->database());
                  pEnt = pArc;
                }
              }
              break;
            case AcGe::kEllipArc2d:
              {
                AcGeEllipArc3d *cArc3d = static_cast<AcGeEllipArc3d *>(gent3d);
                if (cArc3d) {
                  AcGePoint3d p = cArc3d->center();
                  AcDbEllipse *pArc = new AcDbEllipse();
                  pArc->setDatabaseDefaults(pHatch->database());
                  AcGeVector3d majAxis = cArc3d->majorAxis();
                  majAxis *= cArc3d->majorRadius();
                  pArc->set(p,AcGeVector3d::kZAxis,majAxis,cArc3d->minorRadius()/cArc3d->majorRadius(),
                    cArc3d->startAng(),cArc3d->endAng());
                  pArc->setStartParam(cArc3d->startAng());
                  pArc->setEndParam(cArc3d->endAng());
                  AcGePlane plane;
                  AcDb::Planarity pl;
                  pHatch->getPlane(plane,pl);
                  AcGeMatrix3d mat; mat.setToPlaneToWorld(plane);
                  pArc->transformBy(mat);
                  pEnt = pArc;
                }
              }
              break;
            case AcGe::kNurbCurve2d:
              {
                Adesk::Boolean bIsFitSpline;
                AcGePoint3dArray fitPoints;
                AcGeTol fitTol;
                Adesk::Boolean bTangentsExist;
                AcGeVector3d startTangent, endTangent;
                int deg;
                AcGeNurbCurve3d *pGeSpline = static_cast<AcGeNurbCurve3d *>(gent3d);
                deg = pGeSpline->degree();
                bIsFitSpline = pGeSpline->getFitData(fitPoints, fitTol, bTangentsExist, startTangent, endTangent);
                if( bIsFitSpline == Adesk::kTrue) {
                  AcDbSpline *pSpline=new AcDbSpline();
                  pSpline->setFitData(fitPoints, deg, fitTol.equalVector(), startTangent, endTangent);
                  if( pSpline->isNull() == Adesk::kTrue)
                    break;
                  AcGePlane plane;
                  AcDb::Planarity pl;
                  pHatch->getPlane(plane,pl);
                  AcGeMatrix3d mat; mat.setToPlaneToWorld(plane);
                  pSpline->transformBy(mat);
                  pEnt = pSpline;
                } else {
                  Adesk::Boolean rational,closed,periodic;
                  AcGePoint3dArray gePoints;
                  AcGeDoubleArray geWeights;
                  AcGePoint3d gePoint;
                  AcGeKnotVector geKnots;
                  AcGeDoubleArray dKnots;
                  int k=0;
                  rational = pGeSpline->isRational();
                  closed = pGeSpline->isClosed();
                  periodic = Adesk::kFalse;
                  for(k=0; k<pGeSpline->numControlPoints(); k++) {
                    gePoints.append(pGeSpline->controlPointAt(k));
                  }
                  for(k=0; k<pGeSpline->numWeights(); k++) {
                    geWeights.append(pGeSpline->weightAt(k));
                  }
                  geKnots = pGeSpline->knots();
                  for(k=0; k<geKnots.length(); k++) {
                    dKnots.append(geKnots[k]);
                  }
                  AcDbSpline *pSpline = new AcDbSpline(deg, rational, closed,periodic, gePoints, dKnots, geWeights);
                  if( pSpline->isNull() == Adesk::kTrue)
                    break;
                  AcGePlane plane;
                  AcDb::Planarity pl;
                  pHatch->getPlane(plane,pl);
                  AcGeMatrix3d mat; mat.setToPlaneToWorld(plane);
                  pSpline->transformBy(mat);
                  pEnt = pSpline;
                }
              }
              break;
            default:
              {
                if (epx < 0) {
                  if (acedGetDist(NULL,_T("\nЗадайте точность апроксимации <1e-3> : "),&epx) == RTCAN)
                    return;
                  epx = max(epx,1e-6);
                }
                AcGePoint3dArray vertices;
                AcGeDoubleArray  parms;
                AcGeInterval interval; gent3d->getInterval(interval);
                gent3d->getSamplePoints(interval.lowerBound(),interval.upperBound(),epx,vertices,parms);
                if (vertices.length () > 0) {
                  AcDbPolyline *pPoly = new AcDbPolyline(vertices.length());
                  pPoly->setDatabaseDefaults (pHatch->database());
                  for (int j=0; j < vertices.length(); j++) {
                    pPoly->addVertexAt (j,asPnt2d(asDblArray(vertices[j])),0.0);
                  }
                  pPoly->setClosed(gent3d->isClosed());
                  pPoly->setNormal(pHatch->normal());
                  pPoly->setElevation (pHatch->elevation());
                  pEnt = pPoly;
                }
              }
              break;
            }
          } else {
            acutPrintf(_T("\nUnknown type of loop"));
          }
          if (pEnt && postToDatabase (acdbCurDwg()->currentSpaceId(),pEnt)) {
            pEnt->close ();
          } else {
            delete pEnt;
          }
        }
      }
    }
  }
}

Re: Получение контура штриховки

Премного благодарен, Александр!