Преобразование в Display CS

Автор Тема: Преобразование в Display CS  (Прочитано 8634 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Sergey_KАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 2
Преобразование в Display CS
« : 03-03-2020, 16:51:00 »
Текущий вид не совпадает с UCS
Нужно получить крайние видимые точки текущего вида

Как получить вектор нормали к экрану (или матрицу DCS) и параметры вида (крайние точки или центр) ?

VIEWCTR и VIEWDIR возвращают значение в UCS...

Отмечено как Решение Sergey_K 03-03-2020, 17:54:20

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Преобразование в Display CS
« Ответ #1 : 03-03-2020, 16:54:50 »
VIEWCTR и VIEWDIR возвращают значение в UCS...

Функция acedTrans должна помочь тебе преобразовать точку и вектор из UCS в DCS.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Sergey_KАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 2
Re: Преобразование в Display CS
« Ответ #2 : 03-03-2020, 16:59:29 »
Функция acedTrans должна помочь
Это только полдела. Вектор я получу.
Высоту вида допустим получу через VIEWSIZE.
А характерную точку (центр или крайнюю)?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Преобразование в Display CS
« Ответ #3 : 03-03-2020, 17:07:05 »
А характерную точку (центр или крайнюю)?
Центр ты получишь через преобразованный VIEWCTR. Высоту (в единицах чертежа) в VIEWSIZE. Соотношение ширины и высоты активного видового экрана в SCREENSIZE.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Sergey_KАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 2
Re: Преобразование в Display CS
« Ответ #4 : 03-03-2020, 17:21:08 »
Мда, похоже изначально неправильно определил вектор нормали...
через VIEWDIR, вместо acedTrans

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Преобразование в Display CS
« Ответ #5 : 03-03-2020, 17:24:11 »
Мда, похоже изначально неправильно определил вектор нормали...
через VIEWDIR, вместо acedTrans
??? Переведи. Кстати, обрати внимание, что для векторов в acedTrans нужно задавать предпоследний параметр в TRUE, а для точек в FALSE (исправил).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Преобразование в Display CS
« Ответ #6 : 03-03-2020, 17:29:10 »
Нужно получить крайние видимые точки текущего вида
Кстати, ты не уточнил в какой системе координат нужно получить эти точки. Всё, что я писал выше это в предположении, что точки нужно получить в МСК (WCS).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Sergey_KАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 2
Re: Преобразование в Display CS
« Ответ #7 : 03-03-2020, 17:38:41 »
Переведи
Функция у меня работала, пока текущий вид совпадал с UCS. Как только перестал совпадать, обнаружил, что... (причина выяснена).
Цитата:  link=topic=9763.msg43028#msg43028 date=1583245451
для векторов в acedTrans нужно задавать предпоследний параметр в FALSE, а для точек в TRUE
А не наоборот?
Цитата:  link= SDK
If nonzero, pt is treated as a displacement vector; otherwise, it is treated as a point
В какой системе получать точки - не существенно. Преобразования между ними не вызывают трудностей


Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Преобразование в Display CS
« Ответ #8 : 03-03-2020, 17:41:21 »
А не наоборот?
Кстати, обрати внимание, что для векторов в acedTrans нужно задавать предпоследний параметр в TRUE, а для точек в FALSE (исправил).
Т.е. я сразу исправил своё сообщение.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Sergey_KАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 2
Re: Преобразование в Display CS
« Ответ #9 : 03-03-2020, 17:45:29 »
Значит я поздно увидел исправление

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Преобразование в Display CS
« Ответ #10 : 03-03-2020, 17:49:55 »
Sergey_K,
Не забудь отметить решение или (если его здесь нет), то расшифруй чего не хватает...
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Sergey_KАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 2
Re: Преобразование в Display CS
« Ответ #11 : 03-03-2020, 17:53:56 »
Решение - определять нормаль для DCS не через VIEWDIR, а через  acedTrans.

Этого достаточно. Отметил

Оффлайн Sergey_KАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 2
Re: Преобразование в Display CS
« Ответ #12 : 03-03-2020, 19:49:04 »
Что то ерунда получается...
Код - C++ [Выбрать]
  1. AcGePoint3d ucsToDcs(const AcGePoint3d& pt) {
  2.    resbuf fromRb, toRb;
  3.    ads_point newPt;
  4.  
  5.    fromRb.restype = toRb.restype = RTSHORT;
  6.    fromRb.resval.rint = AcDb::kUserCS;
  7.    toRb.resval.rint = AcDb::kCurDisplayCS;
  8.  
  9.    short result = acedTrans(asDblArray(pt), &fromRb, &toRb, FALSE, newPt);
  10.    ASSERT(result == RTNORM);
  11.  
  12.    return asPnt3d(newPt);
  13. }
  14. AcGePoint3d dcsToWcs(const AcGePoint3d& pt) {
  15.    resbuf fromRb, toRb;
  16.    ads_point newPt;
  17.  
  18.    fromRb.restype = toRb.restype = RTSHORT;
  19.    fromRb.resval.rint = AcDb::kCurDisplayCS;
  20.    toRb.resval.rint = AcDb::kWorldCS;
  21.  
  22.    short result = acedTrans(asDblArray(pt), &fromRb, &toRb, FALSE, newPt);
  23.    ASSERT(result == RTNORM);
  24.  
  25.    return asPnt3d(newPt);
  26. }
  27. void viewRect() {
  28.    resbuf rb;
  29.    acedGetVar(_T("VIEWCTR"), &rb);
  30.    AcGePoint3d center(rb.resval.rpoint[X], rb.resval.rpoint[Y], rb.resval.rpoint[Z]);
  31.    center = ucsToDcs(center);
  32.    acedGetVar(_T("VIEWSIZE"), &rb);
  33.    double heigth = rb.resval.rreal;
  34.    acedGetVar(_T("SCREENSIZE"), &rb);
  35.    double width = heigth * rb.resval.rpoint[X] / rb.resval.rpoint[Y];
  36.    AcGePoint3d topLeft((center.x - (width / 2)), (center.y + (heigth / 2)), 0);
  37.    AcGePoint3d bottomright((center.x + (width / 2)), (center.y - (heigth / 2)), 0);
  38.  
  39.    topLeft = dcsToWcs(topLeft);
  40.    bottomright = dcsToWcs(bottomright);
  41.  
  42.    AcDbBlockTable *btbl;  acdbCurDwg()->getBlockTable(btbl);
  43.    AcDbBlockTableRecord *btr; btbl->getAt(ACDB_MODEL_SPACE, btr, AcDb::kForWrite);
  44.    btbl->close();
  45.    AcDbObjectPointer<AcDbLine> l1, l2, l3, l4;
  46.    l1.create(); l2.create(); l3.create(); l4.create();
  47.    l1->setStartPoint(topLeft); l1->setEndPoint(AcGePoint3d(topLeft.x, bottomright.y, 0));
  48.    l2->setStartPoint(l1->endPoint()); l2->setEndPoint(bottomright);
  49.    l3->setStartPoint(bottomright); l3->setEndPoint(AcGePoint3d(bottomright.x, topLeft.y, 0));
  50.    l4->setStartPoint(l3->endPoint()); l4->setEndPoint(topLeft);
  51.    btr->appendAcDbEntity(l1); l1.close();
  52.    btr->appendAcDbEntity(l2); l2.close();
  53.    btr->appendAcDbEntity(l3); l3.close();
  54.    btr->appendAcDbEntity(l4); l4.close();
  55.    btr->close();
  56. }
  57.  



Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Преобразование в Display CS
« Ответ #13 : 03-03-2020, 21:14:07 »
Что то ерунда получается...
И кто бы сомневался? ;) Ну как минимум операции по получению вершин прямоугольника ты должен производить в DCS, а затем преобразовать их в WCS для построения.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Sergey_KАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 2
Re: Преобразование в Display CS
« Ответ #14 : 03-03-2020, 21:17:37 »
Ну как минимум операции по получению вершин прямоугольника ты должен производить в DCS, а затем преобразовать их в WCS для построения

Если смотреть внимательней, именно это я и делаю

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Преобразование в Display CS
« Ответ #15 : 03-03-2020, 21:22:02 »
Ну как минимум операции по получению вершин прямоугольника ты должен производить в DCS, а затем преобразовать их в WCS для построения

Если смотреть внимательней, именно это я и делаю
Нет. Посмотри внимательно.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Sergey_KАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 2
Re: Преобразование в Display CS
« Ответ #16 : 03-03-2020, 21:24:30 »
Внимательней некуда. Конкретнее.
Разве что Z координата

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Преобразование в Display CS
« Ответ #17 : 03-03-2020, 21:26:25 »
И почему ты обнуляешь Z в WCS?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Sergey_KАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 2
Re: Преобразование в Display CS
« Ответ #18 : 03-03-2020, 21:27:29 »
Щас, исправлю Z

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Преобразование в Display CS
« Ответ #19 : 03-03-2020, 21:33:19 »
Внимательней некуда. Конкретнее.
Разве что Z координата
В том виде, что у тебя на рисунке, у всех угловых точек разные координаты Z. Поэтому фортель с тем, что ты преобразовал только topLeft и bottomRight не проходит. Нужно обработать все 4 точки.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Sergey_KАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 2
Re: Преобразование в Display CS
« Ответ #20 : 03-03-2020, 22:05:19 »
Цитата:  link=topic=9763.msg43043#msg43043 date=1583260399
Нужно обработать все 4 точки
Верно. Теперь отрисовывает корректно

И ещё: матрица преобразований dcs в wcs
Код - C++ [Выбрать]
  1.    double k(0.015625);
  2.    resbuf rb;
  3.    acedGetVar(_T("viewdir"), &rb);
  4.    AcGeVector3d zAxis(rb.resval.rpoint[X], rb.resval.rpoint[Y],
  5.          rb.resval.rpoint[Z]), xAxis, yAxis;
  6.    zAxis.normalize();
  7.    zAxis = UcsToDcs(zAxis);
  8.  
  9.    if ((fabs(zAxis.x) < k) && (fabs(zAxis.y) < k))
  10.       xAxis = AcGeVector3d::kYAxis.crossProduct(zAxis);
  11.    else
  12.       xAxis = AcGeVector3d::kZAxis.crossProduct(zAxis);
  13.    xAxis.normalize();
  14.    yAxis = zAxis.crossProduct(xAxis);
  15.    yAxis.normalize();
  16.    
  17.    AcGeMatrix3d dcsToWcs;
  18.    dcsToWcs.setCoordSystem(AcGePoint3d::kOrigin, xAxis, yAxis, zAxis);
  19.  
Ничего не напортачил?
ПС: кроме AcGePoint3d::kOrigin - тоже нужно в DCS

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Преобразование в Display CS
« Ответ #21 : 03-03-2020, 22:15:21 »
Ничего не напортачил?
На первый взгляд всё правильно. Но нужно тестировать. Попробуй на своих четырёх точках.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Преобразование в Display CS
« Ответ #22 : 03-03-2020, 22:25:03 »
Можно сделать иначе без использования VIEWDIR. Глянь код функции Wcs2Dcs отсюда: https://adndevblog.typepad.com/autocad/2012/06/setting-the-view-center-in-an-external-dwg-file-with-objectarx-or-realdwg-in-c.html
Тебе нужно будет только инвертировать результирующую матрицу. Из плюсов той функции - она работает и в перспективном виде.
Пример её использования там же.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Преобразование в Display CS
« Ответ #23 : 04-03-2020, 02:15:27 »
Вот немного упрощенный вариант (без учета перспективы):
Код - C++ [Выбрать]
  1. static void viewRect() {
  2.   AcGeMatrix3d ucs2wcs(Ucs2Wcs());
  3.   AcGeMatrix3d wcs2dcs(Wcs2Dcs());
  4.   AcGeMatrix3d dcs2wcs(Dcs2Wcs());
  5.   resbuf rb;
  6.   acedGetVar(_T("VIEWCTR"), &rb);
  7.   AcGePoint3d center(rb.resval.rpoint[X], rb.resval.rpoint[Y], rb.resval.rpoint[Z]);
  8.   center.transformBy(ucs2wcs).transformBy(wcs2dcs);
  9.   acedGetVar(_T("VIEWSIZE"), &rb);
  10.   double height = rb.resval.rreal;
  11.   acedGetVar(_T("SCREENSIZE"), &rb);
  12.   double width = height * rb.resval.rpoint[X] / rb.resval.rpoint[Y];
  13.   AcGePoint3d p[4] = {
  14.     AcGePoint3d((center.x - (width / 2)), (center.y - (height / 2)), 0),
  15.     AcGePoint3d((center.x - (width / 2)), (center.y + (height / 2)), 0),
  16.     AcGePoint3d((center.x + (width / 2)), (center.y + (height / 2)), 0),
  17.     AcGePoint3d((center.x + (width / 2)), (center.y - (height / 2)), 0)
  18.   };
  19.   AcGePoint3dArray pts;
  20.  
  21.   for (int i = 0; i < 4; i++)
  22.   {
  23.     p[i] = p[i].transformBy(dcs2wcs);
  24.     pts.append(p[i]);
  25.   }
  26.  
  27.   AcDbBlockTableRecordPointer btr(acdbSymUtil()->blockModelSpaceId(acdbCurDwg()), AcDb::kForWrite);
  28.   AcDb3dPolyline *pline = new AcDb3dPolyline(AcDb::Poly3dType::k3dSimplePoly, pts, true);
  29.   btr->appendAcDbEntity(pline);
  30.   pline->close();
  31.  
  32. }
  33.  
  34. static AcGeMatrix3d Ucs2Wcs()
  35. {
  36.   AcGeMatrix3d mat; mat.setToIdentity();
  37.   acedGetCurrentUCS(mat);
  38.   return mat;
  39. }
  40. static AcGeMatrix3d Ucs2Dcs()
  41. {
  42.   return Ucs2Wcs() * Wcs2Dcs();
  43. }
  44. static AcGeMatrix3d Dcs2Ucs()
  45. {
  46.   return Ucs2Dcs().inverse();
  47. }
  48.  
  49. static AcGeMatrix3d Wcs2Ucs()
  50. {
  51.   return Ucs2Wcs().inverse();
  52. }
  53.  
  54. static AcGeMatrix3d Dcs2Wcs()
  55. {
  56.   AcGeMatrix3d mat; mat.setToIdentity();
  57.  
  58.   acedVports2VportTableRecords();
  59.  
  60.   AcDbViewportTableRecordPointer vtr(acedActiveViewportId(), AcDb::kForRead);
  61.   if (vtr.openStatus() == Acad::eOk)
  62.   {
  63.     mat = AcGeMatrix3d::rotation(-vtr->viewTwist(), vtr->viewDirection(), vtr->target()) *
  64.       AcGeMatrix3d::translation(vtr->target().asVector()) *
  65.       AcGeMatrix3d::planeToWorld(vtr->viewDirection());
  66.   }
  67.   return mat;
  68. }
  69. static AcGeMatrix3d Wcs2Dcs()
  70. {
  71.   return Dcs2Wcs().inverse();
  72. }
  73.  
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Sergey_KАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 114
  • Карма: 2
Re: Преобразование в Display CS
« Ответ #24 : 04-03-2020, 12:43:22 »
 :o Столько вариантов ) Dcs2Wcs в тему.

Комбинаций много, а сложных преобразований - не счесть... по надобности.
Преобразования WCS->UCS и обратно, поворот, масштаб, сдвиг - затруднений не вызывают. Были некоторые вопросы с DCS...