Тема: 3D solid

есть 3d полилиния, из которой нужно сделать 3d тело. полилиния - это низ. такая же полилиния, но с другой высотой - верх. грубо говоря делаю три сетки: выдавливание (полилиния нижняя выдавливается на заданню высоту), две сети замыкания (крышка сверху по верхней полилинии и крышка снизу - по нижней). дальше делаю тело на основе этих сетей.
делается, но не всегда :(.
вот функция создания тела

AcDbObjectId add3dSolid(AcDbObjectId poly3dID, // низ нашего солида
            double height, // на сколько поднять верх
            Adesk::UInt16 Color = 0, // цвет, по-умолчанию - текущий
            const ACHAR* Layer = NULL, // слой, по-умолчанию - текущий
            ACHAR * ModelPaperSpace = ACDB_MODEL_SPACE); // куда будем писать. по-умолчанию в пространство модели

AcDbObjectId add3dSolid(AcDbObjectId poly3dID, double height, Adesk::UInt16 Color, const ACHAR* Layer, ACHAR * ModelPaperSpace)
{
    Acad::ErrorStatus es;
    AcDbObjectId eIdTop;
    AcDbObjectId eId = AcDbObjectId::kNull;
    AcDbEntity * pEnt;
    if (Acad::eOk != acdbOpenObject(pEnt,poly3dID,AcDb::kForRead)) return eId;
    AcDbEntity *pEntTop = (AcDbEntity*)pEnt->clone();
    AcGeMatrix3d mat;
    mat.setToTranslation(AcGeVector3d(0.0,0.0,height));
    pEntTop->transformBy(mat);
    es = postToDbase(pEntTop, eIdTop, ModelPaperSpace); // запись объекта в БД чертежа

    pEnt->close();
    AcDb3dProfile *pSweepPerimeter = new AcDb3dProfile(pEnt);
    AcDbSweepOptions swepOptions;
    AcDbObjectId newId;
    AcDbSurface * pPerimeter;
    AcDbSurface * pTop;
    AcDbSurface * pBottom;
    es = AcDbSurface::createExtrudedSurface(pSweepPerimeter,AcGeVector3d(0.0,0.0,height),swepOptions,(AcDbExtrudedSurface*&)pPerimeter);

    AcDb3dProfile *pSweepBottom = new AcDb3dProfile(pEnt);
    AcDbPathRef pathRef;
    pSweepBottom->getPathRef(pathRef);
    AcDbObjectIdArray idArr;
    es = AcDbSurface::createPatchSurface(pathRef, idArr,0,0.0,pBottom);

    AcDb3dProfile *pSweepTop = new AcDb3dProfile(pEntTop);
    AcDbPathRef pathRefTop;
    pSweepTop->getPathRef(pathRefTop);
    idArr.removeAll();
    es = AcDbSurface::createPatchSurface(pathRefTop, idArr,0,0.0,pTop);
    
    AcArray<AcDbEntity*> surfacesArray;
    surfacesArray.append(pPerimeter);
    surfacesArray.append(pTop);
    surfacesArray.append(pBottom);

    AcDb3dSolid *pSolid = new AcDb3dSolid();
    pSolid->setDatabaseDefaults();
    AcGeIntArray limits;
    AcDbEntity *pSurfaceEnt;
 
    es = pSolid->createSculptedSolid(surfacesArray, limits); // иногда не срабатывает
    if(es == Acad::eOk)
    {
        if (Color != 0) pSolid->setColorIndex(Color);
        if (isLayerExists(Layer)) pSolid->setLayer(Layer);
        pSolid->setLinetype(_T("Continuous"));
        es = postToDbase(pSolid, eId, ModelPaperSpace);
        if (es == Acad::eOk)
        {
            es = pSolid->draw();
            es = pSolid->close();
        }
    }
    else
    {
        delete pSolid;
    }

    delete pPerimeter;
    delete pTop;
    delete pBottom;
    delete pSweepBottom;
    delete pSweepTop;
    delete pSweepPerimeter;
    deleteEntities(eIdTop); // удаление с чертежа объекта по ID
    return eId;
}

а вот пример вызова.

static void myProjectmy_test()
{
    ads_name ent;
    AcGePoint3d pt;
    if (acedEntSel(_T("\n3d полилиния: "),ent,asDblArray(pt)) != RTNORM)  return;
    AcDbObjectId eId;
    acdbGetObjectId( eId, ent );
    AcDbObjectId solid3DContourId = add3dSolid(eId,50,1,_T("0"));
}

ну и файл с контурами для Autocad2013 (http://yadi.sk/d/M1RBe5-n354iV)
красный контур не превращается в тело. в чем может быть проблема?\n3d полилиния:

(изменено: Дмитрий Запевалов, 15 мая 2013г. 18:46:40)

Re: 3D solid

А почему AcDb3dSolid::createExtrudedSolid не используешь?

Вообще попробуй сначала создать регион - и посмотри - может больше информации получится (может чего не то с контурами).
Ещё потом тот же регион можно эуструдить
virtual Acad::ErrorStatus extrude(
    const AcDbRegion* region,
    double height,
    double taperAngle = 0.0
);

Re: 3D solid

:) не все так просто. регион нельзя создать на основе 3d-полилинии, у которой все точки не лежат в одной плоскости.
createExtrudedSolid не работает по тем же причинам. точки полилинии не в одной плоскости. единственный вариант заставить работать createExtrudedSolid, это провести триангуляцию всех точек полилинии, выбрать только внутренние треугольники (вдруг контур имеет вогнутые сегменты), а потом эти треугольники подавать на вход. ИМХО через ж... вариант :)
а то, на что натолкнулся я - это баг :):):) и не лечится.
дело в том, что 3dsolid не использует контур, который ему даешь в качестве базы, а делает свой собственный на основе моего, ну и в итоге теряется часть точек на границе (странный механизм потери точек, учитывая то, что все сегменты линейные). и функция createSculptedSolid впадает в ступор на полторы минуты на моем компике пытаясь сшить границы, а потом говорит, что есть дырки между сетями и собрать все в кучу не получится.
вот как-то так. в моем случае пришлось пойти по другому пути, для меня создание 3d тела было делом промежуточным, хоть и важным, но выкрутился и без него (как оказалось, в 12 раз быстрей теперь проходят все вычисления, а точность расчетов та же).

Re: 3D solid

Не понял я что значит

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

провести триангуляцию всех точек полилинии

Видимо всё бы прояснил твой DWG, да у меня не открывается из такого новомодного автокада сделанный :)
А баг видимо с точностью вычислений?

А что обошёлся без солидов - молодец! Всегда заманчиво использовать 3d функционал автокада для вычислений, но это лёгкий путь, чреватый потерями скорости и багами. Я в своё время так с регионами намучался...