Тема: Поворот вокруг заданной точки

Есть у меня Ентити, загруженная из файла....
Нужно ее повернуть вокруг заданной оси, отстоящей от Ентити на заданном расстоянии, т.е. нужно повернуть вокруг точки.
Я использую стандартный метод
xform2.setToRotation(RAD(Value), Axis, Origin);
transformBy(xform2);
Origin - это точка оси Axis вокруг которой нужно вращать на Value градусов.....но почему вращение происходит вокруг центра фигуры а на вокруг точки Origin.......Может что-то подскажет по этому поводу????

Re: Поворот вокруг заданной точки

MnM пишет:

Есть у меня Ентити, загруженная из файла....

Это как понимать? Это твой custom entity или стандартный примитив AutoCAD?

MnM пишет:

Origin - это точка оси Axis вокруг которой нужно вращать на Value градусов.....но почему вращение происходит вокруг центра фигуры а на вокруг точки Origin.......Может что-то подскажет по этому поводу????

Покажи код со значениями оси, типом примитива, значением точки Origion...

Re: Поворот вокруг заданной точки

AcGeVector3d Axis;
        AcGeMatrix3d xform2;
        xform2.setToIdentity();
        if(AxisN == 0){
           Axis.x = 1.0; Axis.y = 0.0;  Axis.z = 0.0;
        }else if(AxisN == 1){
           Axis.x = 0.0; Axis.y = 1.0;  Axis.z = 0.0;
        }else{
           Axis.x = 0.0; Axis.y = 0.0;  Axis.z = 1.0;
        }
                xform2.setToRotation(RAD(Value), Axis, Origin);

char qwe[100];
sprintf(qwe, "AxisN=%d, Angle=%f, Origin(%f,%f,%f)", AxisN, Value, Origin.x, Origin.y, Origin.z);
MessageBoxA(NULL, qwe, "RotateByAxis", NULL);

        TransformByLL(xform2);

Re: Поворот вокруг заданной точки

1. Ты ответил на все поставленные вопросы?
2. Origin передается в МСК (WCS). Ты об этом не забыл?
3. Судя по коду AutoCAD у тебя версии до 2006?

Re: Поворот вокруг заданной точки

Я по автокадом 2010 работаю, версия ObjectARX 2010
AcGePoint3d &Origin, задаю Origin.x, Origin.y, Origin.z


Ентити у меня загружается из файла таким образом
              NewExtDatabase = new AcDbDatabase( Adesk::kFalse );                                              
              if(NewExtDatabase->readDwgFile((const ACHAR*)wBuf) != Acad::eOk){
                  free(wBuf);               
                  bSuccess = false;
                  continue;
              }
              AcDbBlockTable* pBT;
              if(Acad::eOk != NewExtDatabase->getSymbolTable( pBT, AcDb::kForRead )){
                 acutPrintf(L"Couldn't get Symbol Table\n");
                 continue;
              }
              AcDbBlockTableRecord* pBTR;                  
              Acad::ErrorStatus es = pBT->getAt(ACDB_MODEL_SPACE, pBTR, AcDb::kForRead);   
              pBT->close();
              if(Acad::eOk != es){
                 acutPrintf(L"Couldn't get Model Space\n");
                 continue;
              }
              AcDbBlockTableRecordIterator* pIT;
//::MessageBox(NULL, L"Ok", L"Iterator", NULL);
              if(Acad::eOk != pBTR->newIterator( pIT )){
                 acutPrintf(L"New iterator problem\n");
                 pBTR->close();
                 continue;
              }

Вокруг цента фигуры вращение без проблем.....а вот вокруг точки..... вообще я правильно понял работу функции setToRotation????? Мне нужно получить зеркально отображение фигуры, для этого я делаю поворот вокруг оси Y, на 180 градусов, вокруг точки начала координат, в итоге получаю просто поворот вокрут цента фигуры......

Re: Поворот вокруг заданной точки

Присмотрелся к повороту......оказывается поворот происходит вокруг самой верхней левой точки, а не вокруг заданной...

Re: Поворот вокруг заданной точки

Кстати попробовал и для обычной ентити, которая создается так        
SD_Entity *DetEnt = new SD_Entity();
Тоже самое, поворот вокруг заданной точки не получается

Re: Поворот вокруг заданной точки

MnM пишет:

Мне нужно получить зеркально отображение фигуры, для этого я делаю поворот вокруг оси Y, на 180 градусов, вокруг точки начала координат, в итоге получаю просто поворот вокрут цента фигуры......

С каких времен зеркало и поворот стало одним и тем же? Для отзеркаливания нужно использвать метод AcGeMatrix3d::mirroring(). И что такое SD_Entity? Это custom entity?

Re: Поворот вокруг заданной точки

SD_Entity : public AcDbEntity
Все таки почему не работает поворот?

Re: Поворот вокруг заданной точки

MnM пишет:

SD_Entity : public AcDbEntity Все таки почему не работает поворот?

Ты хочешь получить ответ на свой вопрос? Тогда отвечай на мои четко и понятно.
Поворот не работает потому, что ты что-то не то делаешь в методе SD_Entity::subTransformBy

Re: Поворот вокруг заданной точки

В функции subTransformBy: вот что
        assertReadEnabled () ;
        assertWriteEnabled () ;
        AcDbEntity        *PEnt;
        Acad::ErrorStatus Err;
       
        if(SolidId != NULL){       
           Err = acdbOpenAcDbEntity(PEnt,SolidId,AcDb::kForWrite);
           if(Err != Acad::eOk){
              acutPrintf(L"error: open solid entity %x", Err);         
           }else {          
//acutPrintf(L"here solid\n");         
              PEnt->transformBy(xform2);           
           }
           PEnt->close();
        }
        draw();   
Вроде обычный transformBy для объекта PEnt, id которого храниться в SolidId

Re: Поворот вокруг заданной точки

Извини, но у тебя что ни строка - то перл:
1. Кто ставит в методе примитива сразу и assertReadEnabled и assertWriteEnabled - нужно что-то одно, в данном случае assertWriteEnabled
2. Открывать в методе одного примитива другой, а еще и для записи - это мягко говоря опасно.
3. Где ты видел примеры, чтобы сравнивали AcDbObjectId с NULL? Или с AcDbObjectId::kNull или использовать  !SolidId.isNull()
4. Если acdbOpenAcDbEntity вернул не Acad::eOk, то закрывать pEnt нельзя - не открыт он.

Re: Поворот вокруг заданной точки

В том то и дело, что примеров очень мало, в документации на ObjectARX 2010 сухо расписаны классы и все, как их использовать, типичные ситуации не расписаны....приходится самому додумывать, для чего все это количество классов написано.... Вот и спрашиваю Вас почему все таки не правильно работает transformBy(xform2); Он же работает но, не совсем как надо, я не понимаю, почему точку вокруг которой поворачивать он использует другую, хотя ось и угол поворота верно??? вот в чем загадка.....если бы все было не правильно, тогда понятно, а вот наполовину....это загадка....

(изменено: Александр Ривилис, 21 января 2011г. 02:10:56)

Re: Поворот вокруг заданной точки

Вообще-то там всё есть. Но ты похоже начал не с того. Свои примитивы (Custom Entity) можно создавать где-нибудь через годик, после начала изучения ObjectARX. Это сродни тому, как начать играть фуги Баха не научившись играть гаммы. Пока же могу предложить следующее. Нарисуй отрезок (примитив класса AcDbLine) и для него попробуй использовать метод transformBy(), предварительно создав свою матрицу поворота на заданный угол, относительно заданной оси и базовой точки. Проверь результат. Сравни с тем, чего ты ожидал. Ну а потом сможешь двигаться дальше. Здесь готовый пример: https://www.caduser.ru/forum/post170009.html#p170009
P.S.:
1. Пользуйся поиском по форуму, больше чем здесь в русскоязычном интернете по ObjectARX тебе не найти.
2. Учись формулировать вопросы - чем лучше ты их сформулируешь, тем больше вероятность, что ты получишь на них ответы.
3. Если ты подозреваешь, что что-то работает не так, как должно - выкладывай полный код тестового примера, для того чтобы другие могли или убедится в наличии ошибки в AutoCAD, или в твоем коде - не нужно стесняться. Ошибаются все.
4. Помещай код в тэги [code]...твой код...[/code], чтобы его было легко понять и он не искажался.
5. Ну и так далее...  :)

Re: Поворот вокруг заданной точки

В том то и дело, что отдельную точку и отрезок у меня получилось повернуть как надо, относительно заданной точки, а вот созданную ентити не получается....

Re: Поворот вокруг заданной точки

Пункт 3 перечитай.

Re: Поворот вокруг заданной точки

Мне нужно повернуть солид, вокруг заданной оси. Он создается отдельно и Id его хранится в SolidId.

           Solid = new AcDb3dSolid;
           Err = Solid->createBox(xLen, yLen, zLen);
           if(Err != Acad::eOk)acutPrintf(L"error: createBox %x %f %f %f\n", Err, xLen, yLen, zLen);
           AcDbBlockTable *pBlockTable;
           acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pBlockTable, AcDb::kForRead);
           AcDbBlockTableRecord *pBlockTableRecord;
           pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord,AcDb::kForWrite);
           pBlockTable->close();

           SolidId = AcDbObjectId::kNull;    
           Err = acdbHostApplicationServices()->workingDatabase()->addAcDbObject(Solid);
           //Err = pBlockTableRecord->appendAcDbEntity(SolidId, (AcDbEntity*)Solid);               
           Solid->setOwnerId(this->id());
           if(Err != Acad::eOk){            
              acutPrintf(L"error: append entity\n");                     
           }    
           SolidId = Solid->id();             
           acutPrintf(L"ok: append entity %x\n", SolidId);     
           pBlockTableRecord->close();

Попробовал сделать как у Вас в примере, в итоге все равно поворот НЕ вокгруг заданной точки, в данном случае вокруг ОСИ Z  в начале координат, а просто поворот вокруг цента солида.

        AcGePoint3d p1,p2;
        p1.x = 0.0;p1.y = 0.0;p1.z = 0.0;
        p1.x = 0.0;p1.y = 0.0;p1.z = 100.0;
      acdbUcs2Wcs(asDblArray(p1),asDblArray(p1),false);
      acdbUcs2Wcs(asDblArray(p2),asDblArray(p2),false);
      AcGeMatrix3d mat; mat.setToRotation(90,p2-p1,p1);
        if(SolidId != NULL){        
           Err = acdbOpenAcDbEntity(PEnt,SolidId,AcDb::kForWrite);
           if(Err != Acad::eOk){
              acutPrintf(L"error: open solid entity %x", Err);          
           }else {          
//acutPrintf(L"here solid\n");          
              PEnt->transformBy(mat);            

           }
           PEnt->close();
        }

(изменено: Александр Ривилис, 25 января 2011г. 14:12:49)

Re: Поворот вокруг заданной точки

1. Владельцем (Owner) для примитива может быть только AcDbBlockTableRecord. Поэтому, если твой Custom entity унаследован от AcDbEntity делать Solid->setOwnerId(this->id()); нельзя.
2. В моем коде считалось, что пользователь указывает точки в UCS и поэтому они преобразовывались из UCS в WCS. В твоем случае это преобразование делать не нужно, если ты имеешь в виду в качестве базовой точки точку (0,0,0) в WCS.
3. В твоем коде точка p2 вообще не инициализируется - ты дважды задаешь значения для p1
4. Угол в setToRotation задается в радианах, а не в градусах.
Достаточно?

Re: Поворот вокруг заданной точки

Спасибо, за советы! Я Поправил свои ошибки, но в итоге все равно не получается. Такое ощущение, что солид вращается вокруг своей центральной точки, при этом стараясь, чтобы координаты были по всем осям положительными.....

        AcGePoint3d p1;
        AcGeVector3d vec;
        p1.x = 0.0;p1.y = 0.0;p1.z = 0.0;
        vec.x = 0.0;vec.y = 0.0;vec.z = 1.0;


      AcGeMatrix3d mat; mat.setToRotation(RAD(30),vec,p1);
        if(SolidId != NULL){        
           Err = acdbOpenAcDbEntity(PEnt,SolidId,AcDb::kForWrite);           

           if(Err != Acad::eOk){
              acutPrintf(L"error: open solid entity %x", Err);          
           }else {          
//acutPrintf(L"here solid\n");          
              PEnt->transformBy(mat);            

           }
           PEnt->close();
        }

Re: Поворот вокруг заданной точки

А если не внутри своего Custom Entity, то всё нормально?

Re: Поворот вокруг заданной точки

Что значит не внутри своего Custom Entity???? Вы имеете в виду просто создание солида и сразу поворот, без промежуточного хранения???

Re: Поворот вокруг заданной точки

MnM пишет:

Вы имеете в виду просто создание солида и сразу поворот, без промежуточного хранения???

Именно это я и имею в виду.

Re: Поворот вокруг заданной точки

Да тоже самое поворот не вокруг оси Z в начале координат, а поворот вокруг оси Z в точке, где-то внутри самого солида...... :(

Re: Поворот вокруг заданной точки

Засунул поворот в subWorldDraw, которая вызывается каждый раз при обновлении и в ней вызываестя WorldDraw. Получилось, поворот работает как надо, но при каждом обновлении соо-но происходит очередной попорот, мне же надо сделать поворот вне функции subWorldDraw.......

Re: Поворот вокруг заданной точки

MnM пишет:

Да тоже самое поворот не вокруг оси Z в начале координат, а поворот вокруг оси Z в точке, где-то внутри самого солида...... smile:(

Проверил свой код (ссылку на который давал выше) с BOX (0,0,0->10,10,10), ось поворота Z, точка поворота 0,0,0 на угол 30 градусов - всё нормально поворачивает:

Command: box
Specify first corner or [Center]: 0,0,0
Specify other corner or [Cube/Length]: 10,10,10
Command: rot3d
Выберите примитив для вращения:
Укажите первую точку оси - базовую точку для поворота: 0,0,0
Укажите вторую точку оси: 0,0,10
Укажите угол поворота: 30

Результат:
Поворот вокруг заданной точки
В subWorldDraw вставлять поворот нельзя! Она не должна ничего модифицировать.