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

[ACAD 2014] Line moved after drawing it.

6 REPLIES 6
Reply
Message 1 of 7
Anonymous
524 Views, 6 Replies

[ACAD 2014] Line moved after drawing it.

Hi everybody,

I'm experiencing a problem drawing an AcDbLine.

 

I have an entity (HS00Pipe) which inerhits from the AcdbLine entity.

 

When I draw it I use the following procedure:

 

Acad::ErrorStatus Err;
	ads_point pt1, pt2;
	AcGePoint3d pt3d1, pt3d2;

	//primo punto del tubo ()
	if ( acedGetPoint(NULL, _T("Specificare primo punto:"), pt1) != RTNORM )
		return;

	if ( acedGetPoint(pt1, _T("Specificare secondo punto:"), pt2) != RTNORM )
		return;

	pt3d1 = asPnt3d(pt1);
	pt3d2 = asPnt3d(pt2);
	AcGeVector3d v = pt3d1 - pt3d2;


	AcDbBlockTable *pBlockTable;
	if ( acdbHostApplicationServices()->workingDatabase()->getBlockTable (pBlockTable, AcDb::kForRead) == Acad::eOk ) {
		// Get the Model Space record and open it for write. This will be the owner of the new employee entity.
		AcDbBlockTableRecord *pSpaceRecord;
		if ( pBlockTable->getAt (ACDB_MODEL_SPACE, pSpaceRecord, AcDb::kForWrite) == Acad::eOk ) 
		{
			HS00Pipe *pLine = new HS00Pipe(pt3d1, pt3d2);

			AcGePoint3d pt3d1_test, pt3d2_test;
			pLine->getStartPoint(pt3d1_test);
			pLine->getEndPoint(pt3d2_test);


			CAcModuleResourceOverride res;
			CNodeProperty CProp;

			//CProp.m_ID = 0;
			CProp.m_ID_AutoCADProductType = Enum::AutoCADProductTypeEnum::PIPE;
			CProp.m_ID_SAPProductGroup = 0;
			CProp.m_ID_Parent = 0;
			CProp.m_Name.Format(p->get_ShortName() + _T("-%04d"), DocVars.docData().globalobjectcounter++);
			CProp.m_Length = plugin_settings->ScaleFromACADUnitsToMeters( v.length()); // gestione scala
			CProp.m_ID_Drafting_Status = Enum::DraftingStatusEnum::DRAFT;
			CProp.m_ID_Gas = ID_Gas;
			CProp.m_ID_WardSizing = 0;


			if (CProp.DoModal() == IDOK) {
				acutPrintf (_T("\n Aggiornamento nodo\n")) ;


				// Append pEnt to Model Space, then close it and the Model Space record.
				AcDbObjectId idObj;
				pSpaceRecord->appendAcDbEntity (idObj, pLine);

				pLine->close ();
				pSpaceRecord->close () ;

				if ( (Err = acdbOpenAcDbObject ((AcDbObject*&)pLine, idObj, AcDb::kForWrite)) != Acad::eOk ) {
					acutPrintf (_T("\n Errore apertura pLine. (Err=%d)\n"), Err) ;
					return;
				}

				HS00NodeDetails *pNodeDetails = new HS00NodeDetails;

				Logic::CopyDataFromFormToNodeDetail(pNodeDetails, &CProp);
				//aggiungo il fattore di scala per ridimensionare il testo sulla linea
				pNodeDetails->m_scale_factor = ((float)plugin_settings->ScaleFactorFrom/(float)plugin_settings->ScaleFactorTo);
				if ((Err = DraftingTool_SetNodeDetails(pLine, AcDb::kForWrite, pNodeDetails)) == Acad::eOk) {
					acutPrintf (_T("\n Oggetto inserito.\n"));
					pNodeDetails->close();
				}
				else {
					acutPrintf (_T("\n Impossibile aggiungere l'oggetto. (Err=%d)\n"), Err);
					delete pNodeDetails;
				}

				pLine->close();
			}
			else
				delete pLine;

			pSpaceRecord->close () ;
		}
		pBlockTable->close () ;
	}

 

It worked always well with lots of dwg files, but now, trying to draw an HS00Pipe on a certain dwg file I get the line moved after the drawing.

 

I think it could be a problem dued from a particular setting on that dwg file or I missed to handle/override some stuffs inerithing from the acdbline entity.

 

I tried to draw an acdbline with the LINE command and it worked well without moving the line at the end of the drawing.

 

For this reason I think that my entity doesn't handle some offset or particular setting that the acdbline handle well.

 

Drawing my entity on another dwg file works well, so it should be the behaviour of my entity on that dwg file.

 

Here below my entity source code:

 

#include "StdAfx_NodeDetails.h"


//-----------------------------------------------------------------------------
Adesk::UInt32 HS00Pipe::kCurrentVersionNumber =1 ;

//-----------------------------------------------------------------------------
ACRX_DXF_DEFINE_MEMBERS (
	HS00Pipe, AcDbLine,
	AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent, 
	AcDbProxyEntity::kNoOperation, HS00PIPE,
HS00NODEDETAILSAPP
|Product Desc:     A description for your object
|Company:          Your company name
|WEB Address:      Your company WEB site address
)

//-----------------------------------------------------------------------------
HS00Pipe::HS00Pipe () : AcDbLine () {
}

HS00Pipe::HS00Pipe(const AcGePoint3d & start, const AcGePoint3d & end): AcDbLine (start, end) {
}

HS00Pipe::~HS00Pipe () {
}



//-----------------------------------------------------------------------------
//----- AcDbObject protocols
//- Dwg Filing protocol
Acad::ErrorStatus HS00Pipe::dwgOutFields (AcDbDwgFiler *pFiler) const {
	assertReadEnabled () ;
	//----- Save parent class information first.
	Acad::ErrorStatus es =AcDbLine::dwgOutFields (pFiler) ;
	if ( es != Acad::eOk )
		return (es) ;
	//----- Object version number needs to be saved first
	if ( (es =pFiler->writeUInt32 (HS00Pipe::kCurrentVersionNumber)) != Acad::eOk )
		return (es) ;
	//----- Output params
	//.....

	return (pFiler->filerStatus ()) ;
}

Acad::ErrorStatus HS00Pipe::dwgInFields (AcDbDwgFiler *pFiler) {
	assertWriteEnabled () ;
	//----- Read parent class information first.
	Acad::ErrorStatus es =AcDbLine::dwgInFields (pFiler) ;
	if ( es != Acad::eOk )
		return (es) ;
	//----- Object version number needs to be read first
	Adesk::UInt32 version =0 ;
	if ( (es =pFiler->readUInt32 (&version)) != Acad::eOk )
		return (es) ;
	if ( version > HS00Pipe::kCurrentVersionNumber )
		return (Acad::eMakeMeProxy) ;
	//- Uncomment the 2 following lines if your current object implementation cannot
	//- support previous version of that object.
	//if ( version < HS00Pipe::kCurrentVersionNumber )
	//	return (Acad::eMakeMeProxy) ;
	//----- Read params
	//.....

	return (pFiler->filerStatus ()) ;
}

//- Persistent reactor callbacks
void HS00Pipe::openedForModify (const AcDbObject *pDbObj) {
	assertReadEnabled () ;
	AcDbLine::openedForModify (pDbObj) ;
}

void HS00Pipe::cancelled (const AcDbObject *pDbObj) {
	assertReadEnabled () ;
	AcDbLine::cancelled (pDbObj) ;
}

void HS00Pipe::objectClosed (const AcDbObjectId objId) {
	assertReadEnabled () ;
	AcDbLine::objectClosed (objId) ;
}

void HS00Pipe::goodbye (const AcDbObject *pDbObj) {
	assertReadEnabled () ;
	AcDbLine::goodbye (pDbObj) ;
}

void HS00Pipe::copied (const AcDbObject *pDbObj, const AcDbObject *pNewObj) {
	assertReadEnabled () ;
	AcDbLine::copied (pDbObj, pNewObj) ;
}

void HS00Pipe::erased (const AcDbObject *pDbObj, Adesk::Boolean bErasing) {
	assertReadEnabled () ;
	AcDbLine::erased (pDbObj, bErasing) ;
}

void HS00Pipe::modified (const AcDbObject *pDbObj) {
	assertReadEnabled () ;
	AcDbLine::modified (pDbObj) ;
}

void HS00Pipe::modifiedGraphics (const AcDbEntity *pDbEnt) {
	assertReadEnabled () ;
	AcDbLine::modifiedGraphics (pDbEnt) ;
}

void HS00Pipe::modifiedXData (const AcDbObject *pDbObj) {
	assertReadEnabled () ;
	AcDbLine::modifiedXData (pDbObj) ;
}

void HS00Pipe::subObjModified (const AcDbObject *pMainbObj, const AcDbObject *pSubObj) {
	assertReadEnabled () ;
	AcDbLine::subObjModified (pMainbObj, pSubObj) ;
}

void HS00Pipe::modifyUndone (const AcDbObject *pDbObj) {
	assertReadEnabled () ;
	AcDbLine::modifyUndone (pDbObj) ;
}

void HS00Pipe::reappended (const AcDbObject *pDbObj) {
	assertReadEnabled () ;
	AcDbLine::reappended (pDbObj) ;
}

void HS00Pipe::unappended (const AcDbObject *pDbObj) {
	assertReadEnabled () ;
	AcDbLine::unappended (pDbObj) ;
}

//Acad::ErrorStatus HS00Pipe::subIntersectWith(const AcDbEntity* pEnt, AcDb::Intersect intType,const AcGePlane& projPlane, AcGePoint3dArray& points,Adesk::GsMarker thisGsMarker , Adesk::GsMarker otherGsMarker) const
//{
//	assertReadEnabled () ;
//	return AcDbLine::subIntersectWith(pEnt, intType,projPlane, points,thisGsMarker , otherGsMarker);
//}
//
//Acad::ErrorStatus HS00Pipe::subIntersectWith(const AcDbEntity* pEnt, AcDb::Intersect intType, AcGePoint3dArray& points, Adesk::GsMarker thisGsMarker ,Adesk::GsMarker otherGsMarker ) const
//{
//	assertReadEnabled () ;
//	return AcDbLine::subIntersectWith( pEnt,intType,  points, thisGsMarker, otherGsMarker );
//}



//gestione comando _FILLET
Acad::ErrorStatus HS00Pipe::extend(double param)
{
    assertWriteEnabled();
    AcGePoint3d startPnt(startPoint()),
                endPnt(endPoint());
 
    double norm = startPnt.distanceTo(endPnt);
    AcGeLine3d geLine (startPnt, endPnt);
    AcGePointOnCurve3d ponc(geLine);
    if (param > 0.0)
        setEndPoint(ponc.point(param / norm));
    else
        setStartPoint(ponc.point(param / norm));
    return Acad::eOk;
 
}

//-----------------------------------------------------------------------------
//----- AcDbEntity protocols
Adesk::Boolean HS00Pipe::subWorldDraw (AcGiWorldDraw *mode) {

	//scrivo sul tubo il diametro interno e il diametro esterno
	assertReadEnabled () ;
	AcDbLine::subWorldDraw (mode);

	int			internal_diameter;
	int			external_diameter;
	double scale_factor=1.0;
	AcString	pipe_name;
	AcString	pipe_tag;

	//apro il dictionary se riesco///////////////////////////////////////////////////
	AcDbObjectId dict_id;

	if ( (dict_id = this->extensionDictionary()) == AcDbObjectId::kNull ) 
        return Adesk::kTrue;

	AcDbDictionary * pNodeDict = NULL;

	if (GetExtensionDictionary(this, _T("HS00_NODE_DICTIONARY"), AcDb::kForRead, pNodeDict) == Acad::eOk) 
	{
		AcDbObject * pDictNode = NULL;

		if (GetDictionaryNode(pNodeDict, _T("DETAILS"), AcDb::kForWrite, pDictNode) == Acad::eOk) 
		{
			// Check it is a HS00NodeDetails object
			HS00NodeDetails *pNodeDetails = HS00NodeDetails::cast(pDictNode);
			if (pNodeDetails) 
			{
				internal_diameter = pNodeDetails->m_Internal_Diameter;
				external_diameter = pNodeDetails->m_External_Diameter;
				scale_factor= scale_factor*pNodeDetails->m_scale_factor;
				pipe_name = pNodeDetails->m_Name;

				if(pNodeDetails->m_ID_Tag > 0)
					pipe_tag = pNodeDetails->m_TagName;
				else
					pipe_tag = _T("");
				

				pNodeDetails->close();
			}
			pDictNode->close();
		}
		pNodeDict->close();
	}
		
	





    AcGePoint3d position;
    AcGeVector3d norm;
    AcGeVector3d direction; 
    double height,width=1.0, oblique = 0.0; 
	TCHAR buffer [255] = _T("");
	height =0.1;

    AcGePoint3d ptStart, ptEnd;
    getStartPoint(ptStart);
    getEndPoint(ptEnd);
    direction = ptEnd - ptStart;

    norm = normal();

    position = ptStart + (ptEnd - ptStart) / 2.0;
    position.x += 0.04;
    position.y += 0.04;

	//_stprintf (buffer, _T("%s ø %dx%d"),pipe_name.constPtr() , internal_diameter, external_diameter);

	//stampo sul tubo il tag e i diametri
	if(pipe_tag.isEmpty())
		_stprintf (buffer, _T("ø %dx%d") , internal_diameter, external_diameter);
	else
		_stprintf (buffer, _T("[%s] ø %dx%d") , pipe_tag.constPtr() , internal_diameter, external_diameter);

	mode->geometry().text(position, norm, direction, height, width, oblique, buffer);

	//disegno la freccia sul pundo di fine linea//////////////////////////////////////////////////////////////////////////////////////////
	//AcGePoint3d arrow_p1, arrow_p2;
	//AcGeVector3d arrow_v1;
	//arrow_v1 = ptStart - ptEnd;
	//arrow_v1.transformBy(AcGeMatrix3d::scaling(0.02,ptEnd)); //riscalo il vettore (faccio la freccia lunga il 10% della linea)
	//arrow_v1.transformBy(AcGeMatrix3d::rotation(0.5,norm,ptEnd)); //circa 30°
	//arrow_p1 = AcGePoint3d(arrow_v1.x + ptEnd.x,arrow_v1.y + ptEnd.y,arrow_v1.z + ptEnd.z);
	//arrow_v1.transformBy(AcGeMatrix3d::rotation(-1,norm,ptEnd));
	//arrow_p2 = AcGePoint3d(arrow_v1.x + ptEnd.x,arrow_v1.y + ptEnd.y,arrow_v1.z + ptEnd.z);
	
	//AcDbLine l1(ptEnd,arrow_p1), l2(ptEnd,arrow_p2);
	//l1.setLayer(this->layer());
	//l2.setLayer(this->layer());
	//mode->geometry().draw(&l1);
	//mode->geometry().draw(&l2);
	//mode->geometry().draw(&AcDbLine(arrow_p1,arrow_p2));


	//----- Returns Adesk::kTrue to not call viewportDraw()
    return (Adesk::kTrue) ;
}


Adesk::UInt32 HS00Pipe::subSetAttributes (AcGiDrawableTraits *traits) {
	assertReadEnabled () ;
	return (AcDbLine::subSetAttributes (traits)) ;
}

	//- Osnap points protocol
Acad::ErrorStatus HS00Pipe::subGetOsnapPoints (
	AcDb::OsnapMode osnapMode,
	int gsSelectionMark,
	const AcGePoint3d &pickPoint,
	const AcGePoint3d &lastPoint,
	const AcGeMatrix3d &viewXform,
	AcGePoint3dArray &snapPoints,
	AcDbIntArray &geomIds) const
{
	assertReadEnabled () ;
	return (AcDbLine::subGetOsnapPoints (osnapMode, gsSelectionMark, pickPoint, lastPoint, viewXform, snapPoints, geomIds)) ;
}

Acad::ErrorStatus HS00Pipe::subGetOsnapPoints (
	AcDb::OsnapMode osnapMode,
	int gsSelectionMark,
	const AcGePoint3d &pickPoint,
	const AcGePoint3d &lastPoint,
	const AcGeMatrix3d &viewXform,
	AcGePoint3dArray &snapPoints,
	AcDbIntArray &geomIds,
	const AcGeMatrix3d &insertionMat) const
{
	assertReadEnabled () ;
	return (AcDbLine::subGetOsnapPoints (osnapMode, gsSelectionMark, pickPoint, lastPoint, viewXform, snapPoints, geomIds, insertionMat)) ;
}

//- Grip points protocol
Acad::ErrorStatus HS00Pipe::subGetGripPoints (
	AcGePoint3dArray &gripPoints, AcDbIntArray &osnapModes, AcDbIntArray &geomIds
) const {
	assertReadEnabled () ;
	//----- This method is never called unless you return eNotImplemented 
	//----- from the new getGripPoints() method below (which is the default implementation)

	return (AcDbLine::subGetGripPoints (gripPoints, osnapModes, geomIds)) ;
}

Acad::ErrorStatus HS00Pipe::subMoveGripPointsAt (const AcDbIntArray &indices, const AcGeVector3d &offset) {
	assertWriteEnabled () ;
	//----- This method is never called unless you return eNotImplemented 
	//----- from the new moveGripPointsAt() method below (which is the default implementation)

	return (AcDbLine::subMoveGripPointsAt (indices, offset)) ;
}

Acad::ErrorStatus HS00Pipe::subGetGripPoints (
	AcDbGripDataPtrArray &grips, const double curViewUnitSize, const int gripSize, 
	const AcGeVector3d &curViewDir, const int bitflags
) const {
	assertReadEnabled () ;

	//----- If you return eNotImplemented here, that will force AutoCAD to call
	//----- the older getGripPoints() implementation. The call below may return
	//----- eNotImplemented depending of your base class.
	return (AcDbLine::subGetGripPoints (grips, curViewUnitSize, gripSize, curViewDir, bitflags)) ;
}

Acad::ErrorStatus HS00Pipe::subMoveGripPointsAt (
	const AcDbVoidPtrArray &gripAppData, const AcGeVector3d &offset,
	const int bitflags
) {
	assertWriteEnabled () ;

	//----- If you return eNotImplemented here, that will force AutoCAD to call
	//----- the older getGripPoints() implementation. The call below may return
	//----- eNotImplemented depending of your base class.
	return (AcDbLine::subMoveGripPointsAt (gripAppData, offset, bitflags)) ;
}

Acad::ErrorStatus HS00Pipe::GetExtensionDictionary(const AcDbObject * pObj, const TCHAR * strDictName, AcDb::OpenMode mode, AcDbDictionary *& pNodeDict)
{
    // check
    if (pObj == NULL || strDictName == NULL)
        return Acad::eInvalidInput;

    Acad::ErrorStatus Err;

	// Get the Ext. Dictionary
    AcDbObjectId idO ;
	if ( (idO = pObj->extensionDictionary()) == AcDbObjectId::kNull ) {
		// Nothing to do
		//acutPrintf (_T("\nIl nodo non ha un extension dictionary.")) ;
        return Acad::eInvalidObjectId; //TBD
	}

	// If erased, nothing to do
	AcDbDictionary *pExtDict;
	if ( (Err = acdbOpenAcDbObject ((AcDbObject *&)pExtDict, idO, AcDb::kForRead, Adesk::kFalse)) != Acad::eOk ) {
		acutPrintf (_T("\nErrore durante l'apertura dell'extension dictionary. (Err=%d)"), Err) ;
        return Err;
	}

	// See if our dictionary is already there
    AcDbObject *pO;
	if ( (Err = pExtDict->getAt(strDictName, idO)) == Acad::eKeyNotFound ) {
		// Nothing to do if not
		pExtDict->close();
        acutPrintf (_T("\nImpossibile trovare il dictionary '%s'. (Err=%d)"), strDictName, Err);
		return Err;
	} else {
		// Open dictionary for read/write if it is already there
		if ( (Err = acdbOpenAcDbObject (pO, idO, mode)) != Acad::eOk ) {
			pExtDict->close () ;
			acutPrintf (_T("\nImpossibile aprire il dictionary '%s' in lettura. (Err%d)"), strDictName, Err);
			return Err;
		}
		// Check if someone has else has created an entry with our name
		// that is not a dictionary. 
		if ( (pNodeDict =AcDbDictionary::cast (pO)) == NULL ) {
			pO->close ();
			pExtDict->close ();
			acutPrintf (_T("\n'%s' non è un dictionary"), strDictName);
			return Acad::eNotImplementedYet; //TBD
		}

	}
	
    pExtDict->close();

    return Acad::eOk;
}

Acad::ErrorStatus HS00Pipe::GetDictionaryNode(const AcDbDictionary * pDict, const TCHAR * strNodeName, AcDb::OpenMode mode, AcDbObject *& pDictNode)
{
    // check
    if (pDict == NULL || strNodeName == NULL)
        return Acad::eInvalidInput;

    Acad::ErrorStatus Err;

    // Check if a record with this key is already there
    AcDbObjectId idO ;
	if ( (Err = pDict->getAt(strNodeName, idO)) != Acad::eOk ) {
		// Nothing to do
        //acutPrintf (_T("\nImpossibile trovare il nodo '%s'. (Err=%d)"), strNodeName, Err);
		return Acad::eInvalidObjectId; //TBD
	}

	// Open the object with the requested mode (Read or Write)
	if ( (Err = acdbOpenAcDbObject(pDictNode, idO, mode)) != Acad::eOk ) {
        acutPrintf (_T("\nImpossibile aprire il nodo '%s' in lettura. (Err=%d)"), strNodeName, Err);
		return Acad::eNotImplementedYet; //TBD
	}

    return Acad::eOk;
}

AcGePoint3d HS00Pipe::GetOpposedPoint(AcGePoint3d input_point)
{//ritorna il punto opposto a quello fornito serve per evitare di avere tubi direzionali.
	if(input_point == startPoint())
		return endPoint();
	else
		return startPoint();
}

 

 

Thanks for your help.

 

Have a good day,

Massimo.

6 REPLIES 6
Message 2 of 7
owenwengerd
in reply to: Anonymous

The acedGetPoint() function returns a point in UCS, however AcDbLine expects points in WCS. You need to convert your points to WCS:

AcGeMatrix3d mxUCS;
acdbUcsMatrix(mxUCS);
pt3d1.transformBy(mxUCS);
pt3d2.transformBy(mxUCS);

 

--
Owen Wengerd
ManuSoft
Message 3 of 7
Anonymous
in reply to: owenwengerd

Great!

 

It works!

 

Thank you so much,

 

have a good day,

Massimo

Message 4 of 7
Paciguard
in reply to: owenwengerd

Dear Sir:

So while try to use a Line to intersectwith another Line,the error code:"eNotImplementedYet", also means I have to transform the two Lines before they intersected?

If it is, how can I transform them?

Message 5 of 7

This means that the method subIntersectWith is not implemented. If it is a Custom Entity then you have to implement it.

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

Message 6 of 7

thanks a lot. so how can I implement it.

来自我的华为手机
Message 7 of 7
tbrammer
in reply to: Paciguard

> how can I implement it.  (it = intersectWith() )

You can't - unless you implemented the class yourself.

If you want to implement the behaviour of intersectWith() in your own class, you have to overwrite the virtual methods subIntersectWith(). For details refer to the ObjectARX Developer's Guide. See "Intersecting a Custom Entity with Another Entity" and "Intersecting with Other Entities".

Otherwise you can try to call the baseclass explecitely: pLine->AcDbLine::intersectWith(pOther).


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

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

Post to forums  

Autodesk Design & Make Report

”Boost