Regarding the use of AcEdJig class, when AcDbText is being dragged as a mirror,

Regarding the use of AcEdJig class, when AcDbText is being dragged as a mirror,

7598165
Advocate Advocate
2,115 Views
9 Replies
Message 1 of 10

Regarding the use of AcEdJig class, when AcDbText is being dragged as a mirror,

7598165
Advocate
Advocate

Regarding the use of AcEdJig class, when AcDbText is being dragged as a mirror, how to display AcDbText correctly?

mirrtext=0

 

thanks.

0 Likes
2,116 Views
9 Replies
Replies (9)
Message 2 of 10

tbrammer
Advisor
Advisor

I'm not sure what you need exactly. Maybe this code helps:

 

void FlipText()
{
	ads_point    pt;
	ads_name     ent;
	AcDbObjectId objId;

	if (acedEntSel(_T("\nSelect text"), ent, pt) != RTNORM)
		return;

	if (acdbGetObjectId(objId, ent) != Acad::eOk) 
		return;

	// Get the current viewdir
	struct resbuf var;
	acedGetVar(_T("VIEWDIR"), &var);
	AcGeVector3d viewdir;
	acdbUcs2Wcs(var.resval.rpoint, asDblArray(viewdir), true);

	Acad::ErrorStatus es;
	AcDbText *text;
	if ((es = acdbOpenObject(text, objId, AcDb::kForRead)) == Acad::eOk)
	{
		AcGeVector3d normal(text->normal());
		double dp = normal.dotProduct(viewdir);
		if (dp < 0.0) // if <0 we look at the text from the wrong side. Flip it.
		{
			es = text->upgradeOpen();
			if (!es)
			{
				// Flip the normal but keep the insertion/aligment point
				AcDb::TextHorzMode h = text->horizontalMode();
				AcDb::TextVertMode v = text->verticalMode();
				bool bUsePos=((h==AcDb::kTextLeft)&&(v==AcDb::kTextBase));

				AcGePoint3d pt(bUsePos? text->position() : text->alignmentPoint());
				text->setNormal(-normal); // flip the normal

				if (bUsePos)
					es = text->setPosition(pt);		 
				else
					es = text->setAlignmentPoint(pt);
			}
		}
		text->close();
	}
}

 


Thomas Brammer ● Software Developer ● imos AGLinkedIn
If an answer solves your problem please [ACCEPT SOLUTION]. Otherwise explain why not.

0 Likes
Message 3 of 10

7598165
Advocate
Advocate

Thank you! What I want is not the final text result after dragging, but the effect that the text correctly reflects when dragging in AcGeJig.Can you Help me ?

Can you help me? Thanks again! !

0 Likes
Message 4 of 10

tbrammer
Advisor
Advisor

Is the AcDbText your jig->entity()? Then I would assume that have have to make sure that it's normal points along the viewing direction while dragging. This is what my code sample shows.

Could you post sample code that allows me to understand and reproduce your problem?

 

Note:  AcDbText also has these methods:

  Adesk::Boolean isMirroredInX() const;
  Acad::ErrorStatus mirrorInX(Adesk::Boolean);
  Adesk::Boolean isMirroredInY() const;
  Acad::ErrorStatus mirrorInY(Adesk::Boolean);

But they don't take the current viewing direction into account.


Thomas Brammer ● Software Developer ● imos AGLinkedIn
If an answer solves your problem please [ACCEPT SOLUTION]. Otherwise explain why not.

0 Likes
Message 5 of 10

7598165
Advocate
Advocate
virtual Adesk::Boolean  subWorldDraw(AcGiWorldDraw* wd)
{
	wd->geometry().pushModelTransform(m_mat);
	AcDbEntity* pE;
	AcDbRotatedDimension* pDim;
	for (int i = 0; i < m_idArray.length(); i++)
	{
		if (acdbOpenObject(pE, m_idArray[i], AcDb::kForRead) == Acad::eOk)
		{

			///////////////////////////////////////////////////////////////////////////
			// see if the entity is a block reference, if so then check for any attributes so we don't display the 
			// definitions
			AcDbBlockReference* pBlockref = AcDbBlockReference::cast(pE);
			// if it is a block reference
			if (pBlockref != NULL)
			{
				// create an attribute iterator so we can check to see if any attribute asre attached
				AcDbObjectIterator* pAttributeIterator = pBlockref->attributeIterator();
				// if it allocated ok
				if (pAttributeIterator != NULL)
				{
					AcDbObjectId   ObjId;
					AcDbAttribute* pAttribute = NULL;
					// now loop through them
					int count;
					for (count = 0; !pAttributeIterator->done(); pAttributeIterator->step(), ++count)
					{
						// get the object id of the attribute
						ObjId = pAttributeIterator->objectId();
						// open the object so we can draw it
						if (acdbOpenObject(pAttribute, ObjId, AcDb::kForRead) != Acad::eOk)
							continue;
						// now draw it
						wd->geometry().draw(pAttribute);
						// now close the attribute
						pAttribute->close();
					}
					// delete the iterator
					delete pAttributeIterator;
					// see if we have any attributes attached to this block
					// if we have then to stop the attribute definitions being drawn
					if (count)
					{
						AcDbVoidPtrArray entitySet;
						// explode and get some temporary entities
						Acad::ErrorStatus es = pBlockref->explode(entitySet);
						// if it worked ok
						if (es == Acad::eOk)
						{
							// loop round getting the intersection points
							for (long i = 0l; i < entitySet.length(); ++i)
							{
								// get a pointer to the entity object
								AcDbEntity* pNewEnt = (AcDbEntity*)entitySet.at(i);
								AcDbAttributeDefinition* pAttributeDef = AcDbAttributeDefinition::cast(pNewEnt);
								// if it is NOT an attribute definition
								if (pAttributeDef == NULL)
								{
									// then draw it
									wd->geometry().draw(pNewEnt);
								}
								// delete the temporary entity
								delete pNewEnt;
							}
						}
					}
					// no attributes - just draw
					else
					{
						wd->geometry().draw(pE);
					}
				}
				// failed attribute iterator - just draw it
				else
				{
					wd->geometry().draw(pE);
				}
			}
			if (!DocVars.Xd_Kernel.pCurDwg->mirrtext() && (XdGeUtils::IsMirrorMatrix(m_mat)))
			{
				///////////////////////////////////////////
				if (pE->isKindOf(AcDbText::desc()))
				{
					wd->geometry().draw(pE);
//how
				}
				else if (pE->isKindOf(AcDbMText::desc()))
				{
					wd->geometry().draw(pE);
					//how
				}
			}
			// not a block reference - just draw then
			else
			{
				wd->geometry().draw(pE);
			}
			pE->close();
		}
	}
	wd->geometry().popModelTransform();
	return Adesk::kTrue;
}
0 Likes
Message 6 of 10

tbrammer
Advisor
Advisor

I would try something like this:

AcDbText *text = AcDbText::cast(pE);
AcGePoint3d pos(text->position()); // this is the point that will stay fixed
AcGeVector3d zAxis(text->normal);
AcGeVector3d xAxis = zAxis.perpVector().rotateBy(text->rotation(), zAxis);
AcGeVector3d yAxis = zAxis.crossProduct(xAxis);

AcGeMatrix3d mirrMat;
mirrMat.setToAlignCoordSys(
	pos,  xAxis, yAxis, zAxis,
	pos, -xAxis, yAxis, zAxis   // -xAxis to flip the X direction. 
);

wd->geometry().pushModelTransform(mirrMat);
wd->geometry().draw(pE);
wd->geometry().popModelTransform();

Thomas Brammer ● Software Developer ● imos AGLinkedIn
If an answer solves your problem please [ACCEPT SOLUTION]. Otherwise explain why not.

0 Likes
Message 7 of 10

7598165
Advocate
Advocate

mirror.gif

 

Thank you, according to your code, it was partially successful, but in a certain state, the display is not correct, can you solve it when the following picture is shown?

 

搜狗截图20200528110313.jpg

0 Likes
Message 8 of 10

tbrammer
Advisor
Advisor

Sorry, I don't see what you mean.

I've seen the video and the screenshot. The text is rotated but not mirrored.

So what's wrong? How would you expect the text to look like?

 

The only prolems I notices are:

  1. the text appears mirrored right in the moment when you start rotating.
  2. during the rotation the text has an additional offset to the left (about the width of 'ab').

Thomas Brammer ● Software Developer ● imos AGLinkedIn
If an answer solves your problem please [ACCEPT SOLUTION]. Otherwise explain why not.

0 Likes
Message 9 of 10

7598165
Advocate
Advocate

Animation of the AutoCAD mirror command

 

mirror1.gif

 

AcEdJig uses your code, the effect is as follows:

 

When the XDir angle of the AcDbText object is between -pi / 2 and pi / 2, the text is not displayed correctly.

 

virtual Adesk::Boolean  subWorldDraw(AcGiWorldDraw* wd)
{
	wd->geometry().pushModelTransform(m_mat);
	AcDbEntity* pE;
	for (int i = 0; i < m_idArray.length(); i++)
	{
		if (acdbOpenObject(pE, m_idArray[i], AcDb::kForRead) == Acad::eOk)
		{
			if (pE->isKindOf(AcDbText::desc()))
			{
				if (!DocVars.Xd_Kernel.pCurDwg->mirrtext())
				{
					AcGePoint3d ori1;
					AcGeVector3d xAxis1, yAxis1, zAxis1;
					AcDbText* text = AcDbText::cast(pE);
					AcGePoint3d pos(text->position()); // this is the point that will stay fixed
					AcGeVector3d zAxis(text->normal());
					AcGeVector3d xAxis = zAxis.perpVector().rotateBy(text->rotation(), zAxis);
					AcGeVector3d yAxis = zAxis.crossProduct(xAxis);
					AcGePoint3dArray box;
					XdDbUtils::getEntityBoundaryBox(pE, box);
					AcGePoint3d pMid = XdGeUtils::midPoint(box.first(), box[2]);

					AcGeMatrix3d mirrMat;
					mirrMat.setToAlignCoordSys(
						pMid, xAxis, yAxis, zAxis,
						pMid, -xAxis, yAxis, zAxis   // -xAxis to flip the X direction. 
						);
					wd->geometry().pushModelTransform(mirrMat);
					wd->geometry().draw(pE);
				}
				else {
					DocVars.mMirrorResultMatrix = m_mat;
					wd->geometry().draw(pE);
				}
			}
			else
			{
				wd->geometry().draw(pE);
			}
			pE->close();
		}
	}
	wd->geometry().popModelTransform();
	return Adesk::kTrue;
}

mirror.gif

0 Likes
Message 10 of 10

tbrammer
Advisor
Advisor

In the new animation I see what you mean . If the text is rotated by 90°-270° you would expect it to appear "upside down" but instead it is rotated by additional 180° so that it remains readable. Right?

 

I don't think it is related to my mirror-flip code.

I think the text is drawn with one of the two AcGiGeometry::text(..) methods. One passes an AcGiTextStyle and the second one doesn't. It uses a built in style "STANDARD".

AcGiTextStyle has the methods setUpsideDown(bool) and bool isUpsideDown(). As far as I understand the text will
never be drawn upside down if isUpsideDown()==false.

Thomas Brammer ● Software Developer ● imos AGLinkedIn
If an answer solves your problem please [ACCEPT SOLUTION]. Otherwise explain why not.

0 Likes