ObjectARX
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Block Reference Angle Calculation

8 REPLIES 8
SOLVED
Reply
Message 1 of 9
mwst
1278 Views, 8 Replies

Block Reference Angle Calculation

I am dealing with the following problem. I appreciate any help.

 

User gives me three points. I need to create a custom object called valve. The first point is insertion point of the valve. Second point by itself is not important. But the vector from first to second point gives me direction of flow through the valve. The third point gives me the location of the handle of the valve.

 

I need to be able to show the valve using a block reference. For inserting and positioning the block reference correctly, I need to calculate insertion point, normal and angle. I can calcualte insertion point and normal based on the data I have, but calculating correct angle for the block is throwing me off.

 

I can calculate the insertion point as first point + predetermined offset vector.

I can calcualte normal as (vector from P1 to P2).crossProduct (vector from P1 to P3).

 

But I don't know how to calculate the angle through which block must be rotated .

 

If you insert block in any random 3-D plane, how does is it oriented by default? I need to know that after that I can decide how much more it needs to be rotated to point the direction I want.

8 REPLIES 8
Message 2 of 9
owenwengerd
in reply to: mwst

It's much simpler to use transformBy to orient the block reference rather than setting insertion point, normal, and rotation angle separately.

--
Owen Wengerd
ManuSoft
Message 3 of 9
mwst
in reply to: owenwengerd

Hello Owen, thanks for response.

 

I will certainly look into using matrix for setting everything. I can calculate the matrix when I know the normal, point and angle. But for now, my problems is calculating the angle.

 

If I am doing plain simple insert block from Autocad, it always inserts the way the block would have been drawin in UCS. I.e. if the block had an handle and that pointed in Y+ in XY plane when it was drawn, by default Autocad will always insert the block in the XY plane of the UCS and point the handle in Y+.

 

But that does not seem to be the case when I am inserting the block using Objectarx insert block. I can set the UCS to make Y+ point horizontally and still the block gets inserted with the handle pointing vertically.

 

I can't seem to figure out how a block will be inserted in the given plane. Until I figure out how the block is inserted, I cannot calculate the angle through which it must be rotated to make it point in correct direction.

 

Following is my code to do all these calculations. That code is not working the way I expect. Any help is appreciated. The code is not great quality. I am still figuring out the algorithm. Once I figure it out, I will work on good design.

 

	if (m_BlockRef)
	{
		delete m_BlockRef;
		m_BlockRef = nullptr;
	}

	m_DirPt = dir_pt;
	m_BlockRef = new AcDbBlockReference();
	m_BlockRef->setBlockTableRecord(blk_objid);

	// Calcualte Normal : refactor as function
	AcGeVector3d vec = endPoint().asVector() - startPoint().asVector();
	AcGeVector3d vec1 =m_DirPt.asVector() - startPoint().asVector();
	AcGeVector3d vec_normal = vec.crossProduct(vec1);
	vec_normal.normalize();

	// Get UCS, refactor as a function
	AcGeMatrix3d  myUCS;
	acdbUcsMatrix(myUCS, nullptr);
	AcGeVector3d  xAxis, yAxis, zAxis;
	AcGePoint3d   myOrigin;
	myUCS.getCoordSystem(myOrigin, xAxis, yAxis, zAxis);

	bool AngleFlip = false;
	if (fabs (vec_normal.dotProduct(zAxis) ) < 1e-8)
		return;
	else if (vec_normal.dotProduct(zAxis)  < 0)
		AngleFlip = true;
	else
		AngleFlip = false;

	m_BlockRef->setNormal(zAxis) ; //(vec_normal);
	m_BlockRef->setPosition(ins_pt);
	AcGeScale3d scl;
	if (scale < 0)
		scale = 1.0;
	scl.set(scale, scale, scale);
	m_BlockRef->setScaleFactors(scl);

	// calculate angle
	ads_point p_start_wcs, p_end_wcs, p_start_ucs, p_end_ucs;
	p_start_wcs[X] = startPoint().x ; p_start_wcs[Y] = startPoint().y ; p_start_wcs[Z] = startPoint().z;
	p_end_wcs[X] = endPoint().x ; p_end_wcs[Y] = endPoint().y ; p_end_wcs[Z] = endPoint().z;
	ConvertFromWCSToUCS(p_start_wcs, p_start_ucs);
	ConvertFromWCSToUCS(p_end_wcs, p_end_ucs);
	AcGePoint3d p_start(p_start_ucs[X], p_start_ucs[Y], p_start_ucs[Z]);
	AcGePoint3d p_end(p_end_ucs[X], p_end_ucs[Y], p_end_ucs[Z]);
	AcGeVector3d v1_ucs = p_end.asVector() - p_start.asVector();
 	AcGeVector3d v1 = endPoint().asVector() - startPoint().asVector();

	AcGeVector3d ref_vector = AcGeVector3d::kZAxis;
	double dangle  = xAxis.angleTo(v1_ucs, zAxis); // this is not what I want?
	double dangle1 = AcGeVector3d::kXAxis.angleTo(v1_ucs,AcGeVector3d::kZAxis);

	if (m_AngleFlip )
	{
		dangle1 *= -1;
		m_FlipHandle = !m_FlipHandle;
	}
 	m_BlockRef->setRotation(dangle1 );

 

 

 

 

 

Kedar

Message 4 of 9
owenwengerd
in reply to: mwst

Your code should look like this (assuming the block is defined with orthographic orientation -- if not, then you have to use calculated axes instead of the predefined X/Y/Z axes):

 

AcGePoint3d ptTarget = ...;
AcGeVector3d vZAxisTarget = ...;
AcGeVector3d vXAxisTarget = ...;
AcGeVector3d vYAxisTarget = ...;
AcGeMatrix3d mxOrientBlockRef;
mxOrientBlockRef.setToAlignCoordSys(AcGePoint3d::kOrigin, AcGeVector3d::kXAxis, AcGeVector3d::kYAxis, AcGeVector3d::kZAxis, ptTarget, vXAxisTarget, vYAxisTarget, vZAxisTarget);

m_BlockRef = new AcDbBlockReference();
m_BlockRef->setBlockTableRecord(blk_objid);
m_BlockRef->transformBy(mxOrientBlockRef);
//done!

 

--
Owen Wengerd
ManuSoft
Message 5 of 9
mwst
in reply to: owenwengerd

Thanks Owen,

 

By orthographic oientation you mean the front/back/top etc. orientations right? Then yes, the block is defined in top orientation.

 

The way you suggest is more cleaner. It seems to give me what I want when I create the valve with following three points

0,0,0    0,-1,0 1,0,0

 

The first two points define flow direction of the valve, which is indicated using an arrow in the block. The third point defines the direction of the handle in the valve, which is the cross. Please see the attached image.

 

But for the second case, when the input points are as follows

0,0,0 0,-1,0 -1,0,0

It does not give me what I want. In this case, I want the arrow to point in -y direction and the handle to point in -x direction. Again, the image is attached.

 

I am struggling to calculate the angle in such a way that I will get both arrow and handle orientations correct in each plane.

Message 6 of 9
Hallex
in reply to: mwst

Please take a look at this article, it may helps I think:

http://adndevblog.typepad.com/autocad/2012/12/how-to-transform-a-block-reference-and-all-its-attribu...

Cheers

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 7 of 9
owenwengerd
in reply to: mwst

I think you're making it too complicated. Forget about rotation angles. Just align three vectors that define the valve with three vectors in the drawing. It doesn't matter what the directions are, or what the angles are. Simply map the base point of the valve to the insertion point in the drawing and map three vectors on the valve to the corresponding vectors in the drawing.

--
Owen Wengerd
ManuSoft
Message 8 of 9
mwst
in reply to: owenwengerd

Owen,

 

Actually you might be right about this. After eliminating all other calculations and only leaving the code you suggested in place I am getting some results I want. However I need to do testing of several more cases befoe I can say this is the fix. Because I have said that in the past and found another bug little later.

 

Thanks a lot,

 

Kedar

Message 9 of 9
mwst
in reply to: Hallex

Hallex,

 

Thanks for your help too. The article is very useful and I have bookmarked it.

 

Kedar

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost