Тема: правильный getGeomExtents

например, пишу текст в мировой системе координат.
пытаюсь получить его "ограничивающую рамку"

AcDbExtents ext;
pEnt->getGeomExtents(ext);

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

усложняем задачу :)
включаю свободную орбиту, поворачиваю ось плоскость OXY градусов на 30-50, или выставляю новую ПСК по трем точкам (ну тоже чтоб поворот был), а потом выставляю вид в плане по текущей ПСК. потом опять пишу текст и пытаюсь получить эту самую рамку для него.
Ну, в принципе точки на выходе есть, вот только ориентация самой рамки идет под углом, на который я повернул систему координат, хотя текст туда влазит полностью :), а не ограничивает мой текст горизонтальным прямоугольником как в первом случае.

Проверил работу с блоками, та же ерунда. Я так подозреваю, что и остальные акадовские объекты ведут себя подобным образом.

Так вот вопрос. КАК получить GeomExtents для текущего вида указанного объекта, а не для текущей системы координат?

(изменено: Александр Ривилис, 17 марта 2010г. 20:22:06)

Re: правильный getGeomExtents

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

КАК получить GeomExtents для текущего вида указанного объекта, а не для текущей системы координат?

Ну и причем здесь вид объекта, если сам объект повернут? Вот это ты и должен учесть, т.е. развернуть его сначала (его или его клон), получить для него GeomExtents, а потом GeomExtents развернуть в обратном направлении.
P.S.: Кстати в том месте, за участие в котором вы платите немалые деньги, есть пример как получить GeomExtents для повернутого блока.

Re: правильный getGeomExtents

Александр, там не все так просто, если я правильно понял намек :)
правильный getGeomExtents

Да и кроме того, это только для блоков, ну еще можно переделать под размерные стили, хоть мы ими и не пользуемся, ведь только у них и у размеров есть blockTransform(). А как же быть с остальными типами? Да и по поводу вида, все-таки, исходя из картинки, синий и красный контура устраивают, если расположение осей верхнее, а вот, если оси расположены как в левом нижнем углу картинки, то хотелось бы получить что-то похожее на желтый контур.

(изменено: Александр Ривилис, 18 марта 2010г. 12:43:34)

Re: правильный getGeomExtents

Этот вариант рассматривал?

P.S.: Еще один, но трудоемкий вариант (не проверял - на уровне идеи). Преобразовать исходный примитив по матрице преобразования WCS->UCS и получить его getGeomExtents()

Re: правильный getGeomExtents

Ну для текстов эту матрицу можно получить по направлению нормали и углу поворота

если вы об этом

AcGeMatrix3d coordSysMat; 
AcGeVector3d xAxis = pText->normal().perpVector(); 
AcGeVector3d yAxis = pText->normal().crossProduct(xAxis); 
xAxis.rotateBy(pText->rotation(),pText->normal());
yAxis.rotateBy(pText->rotation(),pText->normal());
coordSysMat.setCoordSystem(pText->position(), xAxis, yAxis, pText->normal()); 
extents.transformBy(coordSysMat);

то результат получается как красный контур, хотя и не совсем правильный, т.к. рамочка по-умолчанию поднимается на высоту подстрочной части буквы :), и нада подшаманить, чтоб ее опустить, хотя в "платном" месте :) говорят, что это самый крутой и правильный способ.

PS: единственный способ, который я придумал, это взорвать то что пришло по максимуму :), потом использовать getGripPoints, переводить их в UCS, потом искать минимум и максимум, ну а после этого точки перевести в WCS. Но это так неинтересно :(, кода страницы на 2-3 получится :(
особенно если в блоке есть нелинейные сигменты, да и обрабатывать все типы объектов мягко говоря проблематично, т.к. getGripPoints для текста возвращает очень мало точек, вернее от одной, до четырех (кажется), в зависимости от вариант вставки, так что текст нада хитрым образом разбивать на сегменты, а как это сделать с TTF шрифтом, я даже еще и недумал. нада наверно "помучать" "платное место" :):):)
если ответят что-то внятное, напишу тут.

Re: правильный getGeomExtents

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

потом использовать getGripPoints

Что-то мне это сразу не нравится...

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

нада наверно "помучать" "платное место"

Думаю что ответа будешь ждать порядка месяца.

Re: правильный getGeomExtents

Что-то мне это сразу не нравится...

:) да и я особого восторга не испытываю

Думаю что ответа будешь ждать порядка месяца.

а вариантов все равно нет. на англоязычном форуме нашел подобный одинокий вопрос, заданный в 2002 году :) правда без ответа :):):)
а все остальные рисуют наверно не поворачивая оси координат :), т.к. вопросов не возникает

Re: правильный getGeomExtents

Преобразовать исходный примитив по матрице преобразования WCS->UCS и получить его getGeomExtents()

?

Re: правильный getGeomExtents

Александр, ерунда получается. сейчас попробую описать...
кручу орбитой вокруг плоскости Z. потом ставлю ПСК по виду.
создаю однострочный горизонтальный текст.
так вот, если Z идет из экрана, получаю полный бред :):):), если в экран, то все замечательно. Уже час страдаю ерундой пытаясь понять причину :)

Проверьте у себя, пожалуйста этот код.

AcDbObjectId eId;
AcDbExtents extents;
AcGePoint3d minPt,maxPt;
ads_name ent;
if (acedEntSel(_T("\nВыбери объект: "),ent,asDblArray(maxPt)) != RTNORM) return;
acdbGetObjectId(eId,ent);
if (getBoundingBox_forCurrentView(eId,minPt,maxPt) == Acad::eOk)
{
 // ну и тут создание точек в координатах minPt и maxPt
 // сами координаты в WCS
}

ну и сама функция расчета:

Acad::ErrorStatus getBoundingBox_forCurrentView(AcDbObjectId eId, AcGePoint3d &minPt, AcGePoint3d &maxPt)
{
  Acad::ErrorStatus es;
  AcDbExtents ext;
  AcGeMatrix3d ucsMat;
  acedGetCurrentUCS(ucsMat);
  AcDbEntity * pCopy;
  AcDbObjectPointer<AcDbEntity> pEnt(eId,AcDb::kForRead);
  if ((es = pEnt.openStatus()) != Acad::eOk) return es;
  if ((es = pEnt->getTransformedCopy(ucsMat,(AcDbEntity *&)pCopy)) != Acad::eOk) return es;
  es = pCopy->getGeomExtents(ext);
  delete pCopy;

  minPt = ext.minPoint(); minPt.z = 0.0;
  maxPt = ext.maxPoint(); maxPt.z = 0.0;
  acdbUcs2Wcs(asDblArray(minPt), asDblArray(minPt), false);
  acdbUcs2Wcs(asDblArray(maxPt), asDblArray(maxPt), false);
  return es;
}

(изменено: Александр Ривилис, 18 марта 2010г. 17:46:17)

Re: правильный getGeomExtents

Ты куда-то не туда рулишь IMHO. Ты должен учитывать систему координат примитива-текста (т.е. угол поворота, нормаль и уровень) и систему координат вида. А учитываешь только последнее. Похоже, что нормаль у текста в этом случае переворачивается:

Выбери объект:
Ent Norm=(-0.610639,0.741562,-0.277859)
UCS X =(0.479045,0.694172,-0.537254)
UCS Y =(0.795287,-0.084176,0.600360)
UCS Z =(0.371529,-0.714871,-0.592390)
Command: ucsxdir
UCSXDIR = 0.4790,0.6942,-0.5373 (read only)
Command: ucsydir
UCSYDIR = 0.7953,-0.0842,0.6004 (read only)

P.S.: Я тут подумал, что в твоей функции не хватает ucsMat.invert();

Re: правильный getGeomExtents

Ты должен учитывать систему координат примитива-текста ...

ну вариант

pEnt->getEcs(entMat);
ucsMat = ucsMat * entMat;

я отбросил, т.к. эти строки вообще ни на что не влияли.

а вот

P.S.: Я тут подумал, что в твоей функции не хватает ucsMat.invert();

ДА-ДА, ЭТО ОНО!!!
Спасибо огромное за помощь, Александр.

(изменено: Александр Ривилис, 18 марта 2010г. 18:20:35)

Re: правильный getGeomExtents

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

pEnt->getEcs(entMat);

Это для текста, насколько я помню дает единичную матрицу в любом случае, да и для большинства примитивов тоже. Во всяком случае так было в предыдущих версиях. Так что такую матрицу тебе нужно создавать самому на основе данных примитива. Если для текста ты не учтешь угол поворота, то получишь ерунду. Вот посмотри:

static void ArxProject2tt(void)
{
    // Add your code for command ArxProject2.tt here
    AcDbObjectId eId;
    AcDbExtents extents;
    AcGePoint3d minPt,maxPt;
    ads_name ent;
    if (acedEntSel(_T("\nВыбери объект: "),ent,asDblArray(maxPt)) != RTNORM) return;
    acdbGetObjectId(eId,ent);
    if (getBoundingBox_forCurrentUCS(eId,minPt,maxPt) == Acad::eOk)
    {
       acedGrDraw(asDblArray(minPt),asDblArray(AcGePoint3d(minPt[X],maxPt[Y],0)),1,0);
       acedGrDraw(asDblArray(AcGePoint3d(minPt[X],maxPt[Y],0)),asDblArray(AcGePoint3d(maxPt[X],maxPt[Y],0)),1,0);
       acedGrDraw(asDblArray(AcGePoint3d(maxPt[X],maxPt[Y],0)),asDblArray(AcGePoint3d(maxPt[X],minPt[Y],0)),1,0);
       acedGrDraw(asDblArray(AcGePoint3d(maxPt[X],minPt[Y],0)),asDblArray(minPt),1,0);
    } 
}
Acad::ErrorStatus getBoundingBox_forCurrentUCS(AcDbObjectId eId, AcGePoint3d &minPt, AcGePoint3d &maxPt)
{
  Acad::ErrorStatus es;
  AcDbExtents ext;
  AcGeMatrix3d ucsMat;
  acedGetCurrentUCS(ucsMat);   ucsMat.invert();
  AcDbEntity * pCopy;
  AcDbObjectPointer<AcDbEntity> pEnt(eId,AcDb::kForRead);
  if ((es = pEnt.openStatus()) != Acad::eOk) return es;
  if ((es = pEnt->getTransformedCopy(ucsMat,(AcDbEntity *&)pCopy)) != Acad::eOk) return es;
  es = pCopy->getGeomExtents(ext);
  delete pCopy;

  minPt = ext.minPoint(); minPt.z = 0.0;
  maxPt = ext.maxPoint(); maxPt.z = 0.0;
  //acdbUcs2Wcs(asDblArray(minPt), asDblArray(minPt), false);
  //acdbUcs2Wcs(asDblArray(maxPt), asDblArray(maxPt), false);
  return es;
}

Если текст в UCS не повернут, то вроде бы все нормально. Если повернут - ерунда.
правильный getGeomExtents

Re: правильный getGeomExtents

Если текст в UCS не повернут, то вроде бы все нормально. Если повернут - ерунда

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

PS: еще раз спасибо за помощь.

Re: правильный getGeomExtents

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

PS: еще раз спасибо за помощь.

Рад был помочь. И тебе спасибо за алгоритм работы с EXCEL. А моей "доводкой" этого алгоритма  не воспользовались? Я был очень удивлен тем, во сколько раз увеличивается скорость работы с очень большими таблицами.

Re: правильный getGeomExtents

:) воспользовались.
но пока разницы особо нет, т.к. объемы данных из экселя пока берем по минимуму и выигрыш во времени идет в 4-10 секунд. где-то 5-8 колонок и 50-80 строк.
и еще скоро будем на всю катушку :):):), т.к. прийдется затягивать большие объемы данных из экселя да и еще и из разных файлов, ну и потом по ним строить пласты.
мы в основном из себя в эксель и ворд. как говорится, чем больше бумаги, тем чище за...ца :)
вот и приходится штамповать отчеты. так что в этом плане уже опыта куча :):):) если что, обращайтесь.

Re: правильный getGeomExtents

Договорились!  :)