Тема: Отрисовка элементов в acedDragGen

Если разрешите, два вопроса по acedDragGen:
Можно ли сделать так, чтобы перед тасканием объектов они не отрисовывались на их начальном месте? Они там только загромождают пространство.
Функция работает, но объекты сидят и "дрожат" на своем старом месте, а хотелось бы чтобы они висели на курсоре. Как этого добиться? Неужели их прорисовку надо делать вручную в функции, адрес которой в аргументах?

Re: Отрисовка элементов в acedDragGen

А как тебе такая идея. Перед запуском acedDragGen находишь точку, в которой находится курсор, быстренько перетаскиваешь все примитивы, как будто эта точка базовая и тогда уже запускаешь acedDragGen.

Re: Отрисовка элементов в acedDragGen

Кстати, если ты их будешь создавать invisible, а только перед acedDragGen сделаешь visible, то IMHO будет еще красивее.

Re: Отрисовка элементов в acedDragGen

Насчет видимости понял. Спасибо.
Насчет висения на курсоре не совсем... То есть, чтобы все примитивы перемещались за курсором, я в функции курсора их сам двигаю, или acedDragGen сама это может сделать, и я просто во что-то не въезжаю?

Re: Отрисовка элементов в acedDragGen

Счас накропаю пример.

Re: Отрисовка элементов в acedDragGen

Вот заготовочка, но корректно она работает только в WCS:

  static ads_point  Base;
  static ads_matrix CMT;
  static int DragFunction(ads_point pt, ads_matrix mat)
  {
    ads_point       tp;
    int             axis;
    AcGeVector3d v = asPnt3d(pt) - asPnt3d(Base);
    AcGeMatrix3d gMat; gMat.setToTranslation(v);
    memcpy(mat, gMat.entry, sizeof(ads_matrix));
    memcpy(CMT, mat, sizeof(ads_matrix));
    return RTNORM;
  }
  // - DragSampler.DragSampler command (do not rename)
  static void DragSamplerDragSampler(void)
  {
    // Add your code for command DragSampler.DragSampler here
    ads_name ss;   ads_point p;
    ads_getpoint(NULL, "\nУкажите базовую точку: ", Base);
    if (acedSSGet(NULL,NULL,NULL,NULL,ss) == RTNORM) {
      memcpy(CMT, AcGeMatrix3d::kIdentity.entry, sizeof(ads_matrix));
      if (acedDragGen(ss,"\nНовое место для базовой точки: ",0,DragFunction,p) == RTNORM) {
        acedXformSS(ss,CMT);
      }
    }
  }

Re: Отрисовка элементов в acedDragGen

А так будет работать в любой ПСК:

  static int DragFunction(ads_point pt, ads_matrix mat)
  {
    ads_point       tp;
    int             axis;
    AcGePoint3d pBase = asPnt3d(Base);
    AcGePoint3d pPt = asPnt3d(pt);
    acdbUcs2Wcs(asDblArray(pBase), asDblArray(pBase),false);
    acdbUcs2Wcs(asDblArray(pPt), asDblArray(pPt),false);
    AcGeVector3d v = pPt - pBase;
    AcGeMatrix3d gMat; gMat.setToTranslation(v);
    memcpy(mat, gMat.entry, sizeof(ads_matrix));
    memcpy(CMT, mat, sizeof(ads_matrix));
    return RTNORM;
  }

Re: Отрисовка элементов в acedDragGen

То есть все-таки надо обработку вести в этой функции ...
А можно еще пару вопросов дилетанта?
Что такое AcGeMatrix3d::kIdentity? В хелпе не нашел объяснения.
И еще, не нужно ли проделать те же трансформации с точкой p после ее возвращения?

if (acedDragGen(ss,"\nНовое место для базовой точки:
",0,DragFunction,p) == RTNORM)
...

Она же по идее должна определять окончательное положение...

Re: Отрисовка элементов в acedDragGen

> Леонид
1) AcGeMatrix3d::kIdentity - это диагональная единичная матрица.
2) По поводу точки p после ее возвращения. Я в этом примерчике ею не пользовался и поэтому не преобразовывал, но если она нужна в дальнейшем в WCS, то конечно нужно преобразование UCS->WCS.
Преобразование (перенос) примитивов я делал при помощи acedXformSS(ss,CMT);

Re: Отрисовка элементов в acedDragGen

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

Преобразование (перенос) примитивов я делал при помощи acedXformSS(ss,CMT);

Да, я так и понял. Но меня смутило то, что последний раз матрица CMT формировалась на подлете к окончательной точке, а не после ее получения.
Вероятно, это одно и то же...

Re: Отрисовка элементов в acedDragGen

Леонид пишет:

Но меня смутило то, что последний раз матрица CMT формировалась на подлете к окончательной точке, а не после ее получения.
Вероятно, это одно и то же...

Не подумал. :( Для чистоты эксперимента нужно пользоваться точкой p и с ней провести те же операции, что и с точкой pt внутри DragFunction.

Re: Отрисовка элементов в acedDragGen

Сделать невидимыми получается только все сразу, и исходные элементы, которые уже в базовой точке, и те которые висят на курсоре... отсюда вопрос:
Возможно ли отобразить AcDbEntity на экране, если она не занесена в базу, а просто определена в памяти? что нибудь типа .draw(), только эта функция вываливает автокад... :(

Re: Отрисовка элементов в acedDragGen

Вообще это возможно, но IMHO не для сложных примитивов, так как для них AutoCAD будет искать субпримитивы в базе и это видимо и приводит к развалу AutoCAD. Если это задача все та же (т.е. постоение проекции), то IMHO не стоит сильно усложнять. IMHO если будут видны и исходные элементы и те, что на курсоре, то ничего страшного. Когда я писал о создании примитивов в invisible, то имел в виду, что они такие только в процессе создания, а перед acedDragGen ты:
1) находишь текущую координату курсора в WCS;
2) перетаскиваешь их, совмещая базовую точку в WCS с курсором;
(используя
3) делаешь их visible;
4) запускаешь acedDragGen;

    acedGetPoint(NULL, "\nУкажите базовую точку: ", Base);
    if (acedSSGet(NULL,NULL,NULL,NULL,ss) == RTNORM) {
      ads_point wcsBase;
      acdbUcs2Wcs(Base,wcsBase,false);
      ads_point dcsPt,wcsPt;
      CPoint pt;  GetCursorPos(&pt);
      acedGetAcadDwgView()->ScreenToClient(&pt);
      acedCoordFromPixelToWorld(pt, dcsPt);
      struct resbuf dcs, ucs;
      dcs.restype = RTSHORT; dcs.resval.rint = 2; // DCS
      ucs.restype = RTSHORT; ucs.resval.rint = 0; // WCS
      // Преобразуем координаты курсора в WCS
      acedTrans(dcsPt, &dcs, &ucs, FALSE, wcsPt);
      AcGeMatrix3d mat; mat.setToTranslation(asPnt3d(wcsPt)-asPnt3d(wcsBase));
// Перенесли примитивы в новую базовую точку
      acedXformSS(ss,mat.entry);
      actrTransactionManager->flushGraphics();
      acedUpdateDisplay (); acedPrompt("");
      acdbWcs2Ucs(wcsPt,Base,false);
      memcpy(CMT, AcGeMatrix3d::kIdentity.entry, sizeof(ads_matrix));
//
//  Здесь делаем примитивы видимыми
//
      if (acedDragGen(ss,"\nУкажите новое положение базовой точки: ",0,DragFunction,p) == RTNORM) {
// Здесь нужно сформирвать CMT на основе p
        acedXformSS(ss,CMT);
      }
    }

Есть еще один вариант с использованием AcEdJig, когда ты создаешь свой примитив заглушку, а в его методе worldDraw отрисовываешь все примитивы в новой точке, но это достаточно сложно и в данной задаче я не вижу в этом особого смысла...

Re: Отрисовка элементов в acedDragGen

Да, речь идет по прежнему об аксонометрии и вставке ее в тот же документ, что и модель.
Примитивы при построении используются только AcDbLine и AcDbSpline.
Дело в том, что если оставлять неподвижные элементы видимыми перед их драгом, они существенно загрязняют чертеж во время определения места вставки.
Конечно, это не смертельно, но просто по-человечески хочется их отодвинуть, чтобы они не светили без надобности.
Эти вещи совершенно элементарно делаются в MicroStation, и поэтому я, как лбом о стенку, пытаюсь сделать тоже самое и здесь :)
Ваш код работает, но результат тот же...

        //...........
        ads_name ss2;
        acedSSAdd(NULL, NULL, ss2);
      // AcDbObjectIdArray basket_ids -
            имеющийся набор элементов для отрисовки, который требуется таскать
    
      // добавляем в selection set
        for (int i = 0; i<basket_ids.length(); i++)
        {
            ads_name name;
            Acad::ErrorStatus es = acdbGetAdsName(name, basket_ids[i]);
            if (es == Acad::eOk)
                acedSSAdd(name, ss2, ss2);
        }
        // поехали таскать
        if (!(RTNORM != acedSSLength( ss2, &length ) || 0 == length))
        {
            int rc;
            ads_point return_pt;
            AcGePoint3d Base(0.,0.,0.); // использую центр
            
            //============ Ваш код =================
            ads_point wcsBase;
            acdbUcs2Wcs(asDblArray(Base),wcsBase,false);
            ads_point dcsPt,wcsPt;
            CPoint pt;
            GetCursorPos(&pt);
            acedGetAcadDwgView()->ScreenToClient(&pt);
            acedCoordFromPixelToWorld(pt, dcsPt);
            struct resbuf dcs, ucs;
            dcs.restype = RTSHORT; dcs.resval.rint = 2; // DCS
            ucs.restype = RTSHORT; ucs.resval.rint = 0; // WCS
            // Преобразуем координаты курсора в WCS
            acedTrans(dcsPt, &dcs, &ucs, FALSE, wcsPt);
            AcGeMatrix3d mat; mat.setToTranslation(asPnt3d(wcsPt)-asPnt3d(wcsBase));
            // Перенесли примитивы в новую базовую точку
            acedXformSS(ss2, mat.entry);
            actrTransactionManager->flushGraphics();
            acedUpdateDisplay ();
            acedPrompt("");
            acdbWcs2Ucs(wcsPt,asDblArray(Base),false);
            memcpy(CMT, AcGeMatrix3d::kIdentity.entry, sizeof(ads_matrix));
            //  Здесь делаем примитивы видимыми
            for (int i = 0; i<basket_ids.length(); i++)
            {
                AcDbEntity* pEnt;
                Acad::ErrorStatus es =
                        acdbOpenAcDbEntity(pEnt, basket_ids[i], AcDb::kForWrite);
                if (es == Acad::eOk)
                {
                    pEnt->setVisibility(AcDb::kVisible);
                    pEnt->close();
                }
            }
            if (acedDragGen(
                ss2,
                "\nУкажите точку для центра аксонометрии:\n",
                0,
                drag , // функцию см. ниже
                return_pt
                ) == RTNORM)
            {
                // Здесь нужно сформирвать CMT на основе p
                ads_matrix mat;
                drag(return_pt, mat);
                acedXformSS(ss2,CMT);
            }
            else
            {
                // удаляем все объекты, так как отказались рисовать
                for (int i = 0; i<basket_ids.length(); i++)
                {
                    ads_name name;
                    Acad::ErrorStatus es = acdbGetAdsName(name, basket_ids[i]);
                    if (es == Acad::eOk)
                        acdbEntDel(name);
                }
            }
        }
        acedSSFree( ss2 );
        
        //..............
        //////////////////////////////////////
        // функция динамики курсора
        int drag(ads_point pt, ads_matrix mat)
        {
            ads_point       tp;
            int             axis;
        
            AcGePoint3d pPt = asPnt3d(pt);
            AcGePoint3d pBase(0.,0.,0.);
        
            acdbUcs2Wcs(asDblArray(pBase), asDblArray(pBase),false);
            acdbUcs2Wcs(asDblArray(pPt), asDblArray(pPt),false);
        
            AcGeVector3d v = pPt - pBase;
            AcGeMatrix3d gMat;
            gMat.setToTranslation(v);
        
            memcpy(mat, gMat.entry, sizeof(ads_matrix));
            memcpy(CMT, mat, sizeof(ads_matrix));
        
            return RTNORM;
        }

При acedSSAdd(...) элементы не клонируются?
Мне кажется, собака здесь порылась...
Может просто закинуть все это хозяйство за пределы вьюпорта перед драгом, и все дела...

Re: Отрисовка элементов в acedDragGen

При acedSSAdd(...) элементы не клонируются?

Нет. Они клонируются в acedDragGen.
В принципе их можно закинуть перед драгом за видимые пределы экрана. Думаю, что ничего страшного не произойдет.